From owner-freebsd-security Mon Nov 24 04:36:49 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.7/8.8.7) id EAA29420 for security-outgoing; Mon, 24 Nov 1997 04:36:49 -0800 (PST) (envelope-from owner-freebsd-security) Received: from gatekeeper.tsc.tdk.com (root@gatekeeper.tsc.tdk.com [207.113.159.21]) by hub.freebsd.org (8.8.7/8.8.7) with ESMTP id EAA29413 for ; Mon, 24 Nov 1997 04:36:45 -0800 (PST) (envelope-from gdonl@tsc.tdk.com) Received: from sunrise.gv.tsc.tdk.com (root@sunrise.gv.tsc.tdk.com [192.168.241.191]) by gatekeeper.tsc.tdk.com (8.8.4/8.8.4) with ESMTP id DAA19889 for ; Mon, 24 Nov 1997 03:39:26 -0800 (PST) Received: from salsa.gv.tsc.tdk.com (salsa.gv.tsc.tdk.com [192.168.241.194]) by sunrise.gv.tsc.tdk.com (8.8.5/8.8.5) with ESMTP id DAA14975 for ; Mon, 24 Nov 1997 03:39:25 -0800 (PST) Received: (from gdonl@localhost) by salsa.gv.tsc.tdk.com (8.8.5/8.8.5) id DAA21524; Mon, 24 Nov 1997 03:36:41 -0800 (PST) From: Don Lewis Message-Id: <199711241136.DAA21524@salsa.gv.tsc.tdk.com> Date: Mon, 24 Nov 1997 03:36:41 -0800 In-Reply-To: Don Lewis "Re: new TCP/IP bug in win95 (fwd)" (Nov 21, 4:37pm) X-Mailer: Mail User's Shell (7.2.6 alpha(3) 7/19/95) To: Don Lewis , Jim Shankland , robert@cyrus.watson.org Subject: Re: new TCP/IP bug in win95 (fwd) Cc: security@freebsd.org Sender: owner-freebsd-security@freebsd.org X-Loop: FreeBSD.org Precedence: bulk On Nov 21, 4:37pm, Don Lewis wrote: } Subject: Re: new TCP/IP bug in win95 (fwd) } --- tcp_input.c.prev Fri Nov 21 04:34:51 1997 } +++ tcp_input.c Fri Nov 21 16:32:10 1997 } @@ -752,6 +752,18 @@ } } } } /* } + * If the state is SYN_RCVD: } + * If seg contains a SYN,ACK, then drop it and send a RST. } + * We should only ever get an ACK or a duplicate SYN (if our } + * SYN,ACK was lost) in this state. } + * Otherwise continue processing } + */ } + case TCPS_SYN_RECEIVED: } + if ((tiflags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) } + goto dropwithreset; } + break; /* continue normal processing */ } + } + /* } * 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. }-- End of excerpt from Don Lewis I'm pretty sure this breaks simultaneous opens and self-connects, so how about the following? --- tcp_input.c.prev Fri Nov 21 04:34:51 1997 +++ tcp_input.c Mon Nov 24 03:12:11 1997 @@ -752,6 +752,32 @@ } /* + * If the state is SYN_RCVD: + * If the segment contains a SYN and the sequence number + * doesn't match the initial receive sequence number which + * was set by the previous SYN, drop the segment and send + * a RST. + * + * We'd also like to drop the segment and send a RST if + * the segment contains SYN-ACK, but we'll receive this + * in the (uncommon) simultaneous open or self-connect + * cases. In the usual case, we should only ever get an + * ACK or a duplicate SYN (if our SYN-ACK was lost) in + * this state. It would be ideal if we could perform this + * additional check if the previous state was LISTEN and + * skip this check if the previous state was SYN_SENT. + * As it stands, it's possible for a forged SYN to cause + * us to do a self-connect on a listening socket if the + * proper sequence number can be guessed. + * + * Otherwise continue processing + */ + case TCPS_SYN_RECEIVED: + if ((tiflags & TH_SYN) && ti->seq != tp->irs) + goto dropwithreset; + break; /* continue normal processing */ + + /* * 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. BTW, does anyone else think that instead of "goto dropwithreset" that this should be a call to tcp_drop()? If we tell our client to go away, it would seem there's no sense in keeping our socket around until it times out, though I suppose it will go away when we retry the SYN-ACK and get a RST. I might also be convinced that this should just be "goto drop". Likewise in the code below: /* * Ack processing. */ 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. */ case TCPS_SYN_RECEIVED: if (SEQ_GT(tp->snd_una, ti->ti_ack) || SEQ_GT(ti->ti_ack, tp->snd_max)) goto dropwithreset; Also the following looks wrong to me. Doesn't it end up sending two RST packets? /* * If a SYN is in the window, then this is an * error and we send an RST and drop the connection. */ if (tiflags & TH_SYN) { tp = tcp_drop(tp, ECONNRESET); goto dropwithreset; }