From 606a03ebe5beda6ea740330bf2295c7adc7f4101 Mon Sep 17 00:00:00 2001 From: fenner Date: Wed, 21 Jan 1998 02:05:59 +0000 Subject: A more complete fix for the "land" attack, removing the "quick fix" from rev 1.66. This fix contains both belt and suspenders. Belt: ignore packets where src == dst and srcport == dstport in TCPS_LISTEN. These packets can only legitimately occur when connecting a socket to itself, which doesn't go through TCPS_LISTEN (it goes CLOSED->SYN_SENT->SYN_RCVD-> ESTABLISHED). This prevents the "standard" "land" attack, although doesn't prevent the multi-homed variation. Suspenders: send a RST in response to a SYN/ACK in SYN_RECEIVED state. The only packets we should get in SYN_RECEIVED are 1. A retransmitted SYN, or 2. An ack of our SYN/ACK. The "land" attack depends on us accepting our own SYN/ACK as an ACK; in SYN_RECEIVED state; this should prevent all "land" attacks. We also move up the sequence number check for the ACK in SYN_RECEIVED. This neither helps nor hurts with respect to the "land" attack, but puts more of the validation checking in one spot. PR: kern/5103 --- sys/netinet/tcp_input.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'sys/netinet/tcp_input.c') diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index ca4430d..0fe6d37 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)tcp_input.c 8.12 (Berkeley) 5/24/95 - * $Id: tcp_input.c,v 1.66 1997/11/20 20:04:49 wollman Exp $ + * $Id: tcp_input.c,v 1.67 1997/12/19 23:46:15 bde Exp $ */ #include "opt_tcpdebug.h" @@ -317,19 +317,6 @@ tcp_input(m, iphlen) #endif /* TUBA_INCLUDE */ /* - * Reject attempted self-connects. XXX This actually masks - * a bug elsewhere, since self-connect should work. - * However, a urrently-active DoS attack in the Internet - * sends a phony self-connect request which causes an infinite - * loop. - */ - if (ti->ti_src.s_addr == ti->ti_dst.s_addr - && ti->ti_sport == ti->ti_dport) { - tcpstat.tcps_badsyn++; - goto drop; - } - - /* * Check that TCP offset makes sense, * pull out TCP options and adjust length. XXX */ @@ -626,6 +613,7 @@ findpcb: * If the state is LISTEN then ignore segment if it contains an RST. * If the segment contains an ACK then it is bad and send a RST. * If it does not contain a SYN then it is not interesting; drop it. + * If it is from this socket, drop it, it must be forged. * Don't bother responding if the destination was a broadcast. * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial * tp->iss, and send a segment: @@ -644,6 +632,9 @@ findpcb: goto dropwithreset; if ((tiflags & TH_SYN) == 0) goto drop; + if ((ti->ti_dport == ti->ti_sport) && + (ti->ti_dst.s_addr == ti->ti_src.s_addr)) + goto drop; /* * RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN * in_broadcast() should never return true on a received @@ -762,6 +753,23 @@ findpcb: } /* + * If the state is SYN_RECEIVED: + * if seg contains SYN/ACK, send a RST. + * if seg contains an ACK, but not for our SYN/ACK, send a RST. + */ + case TCPS_SYN_RECEIVED: + if (tiflags & TH_ACK) { + if (tiflags & TH_SYN) { + tcpstat.tcps_badsyn++; + goto dropwithreset; + } + if (SEQ_LEQ(ti->ti_ack, tp->snd_una) || + SEQ_GT(ti->ti_ack, tp->snd_max)) + goto dropwithreset; + } + break; + + /* * If the state is SYN_SENT: * if seg contains an ACK, but not for our SYN, drop the input. * if seg contains a RST, then drop the connection. @@ -1176,14 +1184,11 @@ trimthenstep6: switch (tp->t_state) { /* - * In SYN_RECEIVED state if the ack ACKs our SYN then enter - * ESTABLISHED state and continue processing, otherwise - * send an RST. + * In SYN_RECEIVED state, the ack ACKs our SYN, so enter + * ESTABLISHED state and continue processing. + * The ACK was checked above. */ case TCPS_SYN_RECEIVED: - if (SEQ_GT(tp->snd_una, ti->ti_ack) || - SEQ_GT(ti->ti_ack, tp->snd_max)) - goto dropwithreset; tcpstat.tcps_connects++; soisconnected(so); -- cgit v1.1