Index: tcp_input.c =================================================================== RCS file: /cvsroot/src/sys/netinet/tcp_input.c,v retrieving revision 1.266 diff -u -r1.266 tcp_input.c --- tcp_input.c 18 May 2007 21:48:43 -0000 1.266 +++ tcp_input.c 18 May 2007 23:45:03 -0000 @@ -977,6 +977,10 @@ #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; @@ -1138,6 +1142,10 @@ 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 @@ -1612,13 +1620,17 @@ * 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); } @@ -2158,7 +2170,12 @@ 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; @@ -2688,13 +2705,26 @@ 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); @@ -2735,7 +2765,7 @@ } struct secasvar * -tcp_signature_getsav(struct mbuf *m, struct tcphdr *th) +tcp_signature_getsav(struct mbuf *m) { struct secasvar *sav; #ifdef FAST_IPSEC @@ -2784,7 +2814,7 @@ 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 */ } @@ -2857,7 +2887,35 @@ return (0); } -#endif + +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) + /* + * XXX: I should check the signature + * also increment counters... + */ + return 1; + i += cp[i+1]; + } + +return 0; +} + +#endif /* TCP_SIGNATURE */ static int tcp_dooptions(struct tcpcb *tp, const u_char *cp, int cnt, @@ -2978,7 +3036,7 @@ 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; @@ -2992,7 +3050,7 @@ #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); @@ -3026,7 +3084,7 @@ } 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); @@ -3447,8 +3505,8 @@ 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); } @@ -3775,7 +3833,8 @@ 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); @@ -4251,7 +4310,7 @@ struct secasvar *sav; u_int8_t *sigp; - sav = tcp_signature_getsav(m, th); + sav = tcp_signature_getsav(m); if (sav == NULL) { if (m) Index: tcp_output.c =================================================================== RCS file: /cvsroot/src/sys/netinet/tcp_output.c,v retrieving revision 1.159 diff -u -r1.159 tcp_output.c --- tcp_output.c 18 May 2007 21:48:43 -0000 1.159 +++ tcp_output.c 18 May 2007 23:45:03 -0000 @@ -574,6 +574,7 @@ struct sackhole *p; #ifdef TCP_SIGNATURE int sigoff = 0; + struct secasvar *sav; #endif #ifdef DIAGNOSTIC @@ -1105,9 +1106,16 @@ 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; + } } } } @@ -1169,18 +1177,19 @@ * 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 */ @@ -1379,10 +1388,9 @@ #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: tcp_subr.c =================================================================== RCS file: /cvsroot/src/sys/netinet/tcp_subr.c,v retrieving revision 1.214 diff -u -r1.214 tcp_subr.c --- tcp_subr.c 2 May 2007 20:40:25 -0000 1.214 +++ tcp_subr.c 18 May 2007 23:45:03 -0000 @@ -594,7 +594,7 @@ */ 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; @@ -606,6 +606,9 @@ 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 @@ -725,12 +728,25 @@ 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; @@ -757,8 +773,20 @@ 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; @@ -806,12 +834,33 @@ 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: tcp_timer.c =================================================================== RCS file: /cvsroot/src/sys/netinet/tcp_timer.c,v retrieving revision 1.76 diff -u -r1.76 tcp_timer.c --- tcp_timer.c 9 Oct 2006 16:27:07 -0000 1.76 +++ tcp_timer.c 18 May 2007 23:45:03 -0000 @@ -566,11 +566,21 @@ */ (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, tcp_keepintvl); } else Index: tcp_usrreq.c =================================================================== RCS file: /cvsroot/src/sys/netinet/tcp_usrreq.c,v retrieving revision 1.131 diff -u -r1.131 tcp_usrreq.c --- tcp_usrreq.c 4 Mar 2007 06:03:22 -0000 1.131 +++ tcp_usrreq.c 18 May 2007 23:45:03 -0000 @@ -694,10 +694,10 @@ #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: tcp_var.h =================================================================== RCS file: /cvsroot/src/sys/netinet/tcp_var.h,v retrieving revision 1.146 diff -u -r1.146 tcp_var.h --- tcp_var.h 2 May 2007 20:40:25 -0000 1.146 +++ tcp_var.h 18 May 2007 23:45:03 -0000 @@ -828,9 +828,10 @@ 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 *); @@ -863,7 +864,7 @@ 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