Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 17 Dec 2000 23:41:19 +0100
From:      Jesper Skriver <jesper@skriver.dk>
To:        freebsd-net@FreeBSD.org, cvs-all@FreeBSD.org
Cc:        Kris Kennaway <kris@FreeBSD.ORG>, Poul-Henning Kamp <phk@FreeBSD.ORG>, cvs-committers@FreeBSD.ORG, security-officer@FreeBSD.ORG, "Louis A. Mamakos" <louie@TransSys.COM>
Subject:   Re: cvs commit: src/sys/netinet ip_icmp.c tcp_subr.c tcp_var.h
Message-ID:  <20001217234119.A90024@skriver.dk>
In-Reply-To: <20001217200425.D34282@skriver.dk>; from jesper@skriver.dk on Sun, Dec 17, 2000 at 08:04:25PM %2B0100
References:  <200012161942.eBGJg7j93654@freefall.freebsd.org> <20001217012007.A18038@citusc.usc.edu> <200012171529.eBHFT4512582@whizzo.transsys.com> <20001217182056.B34282@skriver.dk> <20001217183016.C34282@skriver.dk> <20001217200425.D34282@skriver.dk>

next in thread | previous in thread | raw e-mail | index | archive | help

--4Ckj6UjgE2iN1+kY
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Sun, Dec 17, 2000 at 08:04:25PM +0100, Jesper Skriver wrote:

> The only thing I can see, we can do to improve the security of this,
> would be to match agaist the TCP sequence number too, I have a patch for
> this too, but I need to test it, will be back.

Attached is a diff which implement this, it's very strict and require
that the sequence number we get is == the last unacknowledged packet we
sent, thus only working with one unacknowledged packet.

Later (probably tomorrow) I'll look at ways of getting it to work with
multiple outstanding packets.

But somone probably wants to commit the attached, as it's significant
better than what's currently in the tree.

/Jesper

-- 
Jesper Skriver, jesper(at)skriver(dot)dk  -  CCIE #5456
Work:    Network manager @ AS3292 (Tele Danmark DataNetworks)
Private: Geek            @ AS2109 (A much smaller network ;-)

One Unix to rule them all, One Resolver to find them,
One IP to bring them all and in the zone to bind them.

--4Ckj6UjgE2iN1+kY
Content-Type: text/plain; charset=us-ascii
Content-Description: tcp_drop_icmp_unreach.diff
Content-Disposition: attachment; filename="tcp_drop_icmp_unreach.diff"

diff -ru sys/netinet.old/in_pcb.c sys/netinet/in_pcb.c
--- sys/netinet.old/in_pcb.c	Sun Dec 17 18:57:24 2000
+++ sys/netinet/in_pcb.c	Sun Dec 17 23:32:45 2000
@@ -62,6 +62,8 @@
 #include <netinet/in_pcb.h>
 #include <netinet/in_var.h>
 #include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcp_var.h>
 #ifdef INET6
 #include <netinet/ip6.h>
 #include <netinet6/ip6_var.h>
@@ -667,13 +669,14 @@
  * any errors for each matching socket.
  */
 void
-in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify)
+in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify, tcp_sequence)
 	struct inpcbhead *head;
 	struct sockaddr *dst;
 	u_int fport_arg, lport_arg;
 	struct in_addr laddr;
 	int cmd;
 	void (*notify) __P((struct inpcb *, int));
+	u_int32_t tcp_sequence;
 {
 	register struct inpcb *inp, *oinp;
 	struct in_addr faddr;
@@ -716,6 +719,17 @@
 		    (fport && inp->inp_fport != fport)) {
 			inp = inp->inp_list.le_next;
 			continue;
+		}
+		/*
+		 * If tcp_sequence is set, then only match sessions
+		 * where last packet sent had this sequence number.
+		 */
+		if (tcp_sequence) {
+		    struct tcpcb *tp = intotcpcb(inp);
+		    if (tp->snd_una != tcp_sequence) {
+			inp = inp->inp_list.le_next;
+			continue;
+		    }
 		}
 		oinp = inp;
 		inp = inp->inp_list.le_next;
diff -ru sys/netinet.old/in_pcb.h sys/netinet/in_pcb.h
--- sys/netinet.old/in_pcb.h	Sun Dec 17 18:57:24 2000
+++ sys/netinet/in_pcb.h	Sun Dec 17 22:47:39 2000
@@ -290,7 +290,7 @@
 			       struct in_addr, u_int, struct in_addr, u_int,
 			       int, struct ifnet *));
 void	in_pcbnotify __P((struct inpcbhead *, struct sockaddr *,
-	    u_int, struct in_addr, u_int, int, void (*)(struct inpcb *, int)));
+	    u_int, struct in_addr, u_int, int, void (*)(struct inpcb *, int), u_int32_t));
 void	in_pcbrehash __P((struct inpcb *));
 int	in_setpeeraddr __P((struct socket *so, struct sockaddr **nam));
 int	in_setsockaddr __P((struct socket *so, struct sockaddr **nam));
diff -ru sys/netinet.old/tcp_subr.c sys/netinet/tcp_subr.c
--- sys/netinet.old/tcp_subr.c	Sun Dec 17 18:57:24 2000
+++ sys/netinet/tcp_subr.c	Sun Dec 17 23:21:07 2000
@@ -139,7 +139,7 @@
  * as required by rfc1122 section 3.2.2.1
  */
  
-static int	icmp_admin_prohib_like_rst = 0;
+static int	icmp_admin_prohib_like_rst = 1;
 SYSCTL_INT(_net_inet_tcp, OID_AUTO, icmp_admin_prohib_like_rst, CTLFLAG_RW,
 	&icmp_admin_prohib_like_rst, 0, "Treat ICMP administratively prohibited messages like TCP RST, rfc1122 section 3.2.2.1");
 
@@ -967,11 +967,12 @@
 	register struct ip *ip = vip;
 	register struct tcphdr *th;
 	void (*notify) __P((struct inpcb *, int)) = tcp_notify;
+	tcp_seq tcp_sequence = 0;
 
 	if (cmd == PRC_QUENCH)
 		notify = tcp_quench;
 	else if ((icmp_admin_prohib_like_rst == 1) && (cmd == PRC_UNREACH_PORT) && (ip))
-		notify = tcp_drop_syn_sent;
+		notify = tcp_drop_icmp_unreach;
 	else if (cmd == PRC_MSGSIZE)
 		notify = tcp_mtudisc;
 	else if (!PRC_IS_REDIRECT(cmd) &&
@@ -980,10 +981,12 @@
 	if (ip) {
 		th = (struct tcphdr *)((caddr_t)ip 
 				       + (IP_VHL_HL(ip->ip_vhl) << 2));
+		if ((icmp_admin_prohib_like_rst == 1) && (cmd == PRC_UNREACH_PORT))
+			tcp_sequence = ntohl(th->th_seq);
 		in_pcbnotify(&tcb, sa, th->th_dport, ip->ip_src, th->th_sport,
-			cmd, notify);
+			cmd, notify, tcp_sequence);
 	} else
-		in_pcbnotify(&tcb, sa, 0, zeroin_addr, 0, cmd, notify);
+		in_pcbnotify(&tcb, sa, 0, zeroin_addr, 0, cmd, notify, 0);
 }
 
 #ifdef INET6
@@ -1086,16 +1089,16 @@
 
 /*
  * When a ICMP unreachable is recieved, drop the
- * TCP connection, but only if in SYN_SENT
+ * TCP connection
  */
 void
-tcp_drop_syn_sent(inp, errno)
+tcp_drop_icmp_unreach(inp, errno)
 	struct inpcb *inp;
 	int errno;
 {
 	struct tcpcb *tp = intotcpcb(inp);
-	if((tp) && (tp->t_state == TCPS_SYN_SENT))
-			tcp_drop(tp, errno);
+	if(tp)
+		tcp_drop(tp, errno);
 }
 
 /*
diff -ru sys/netinet.old/tcp_var.h sys/netinet/tcp_var.h
--- sys/netinet.old/tcp_var.h	Sun Dec 17 18:57:24 2000
+++ sys/netinet/tcp_var.h	Sun Dec 17 23:17:55 2000
@@ -387,7 +387,7 @@
 void	 tcp_input __P((struct mbuf *, int, int));
 void	 tcp_mss __P((struct tcpcb *, int));
 int	 tcp_mssopt __P((struct tcpcb *));
-void	 tcp_drop_syn_sent __P((struct inpcb *, int));
+void	 tcp_drop_icmp_unreach __P((struct inpcb *, int));
 void	 tcp_mtudisc __P((struct inpcb *, int));
 struct tcpcb *
 	 tcp_newtcpcb __P((struct inpcb *));
diff -ru sys/netinet.old/udp_usrreq.c sys/netinet/udp_usrreq.c
--- sys/netinet.old/udp_usrreq.c	Sun Dec 17 18:57:24 2000
+++ sys/netinet/udp_usrreq.c	Sun Dec 17 19:59:53 2000
@@ -512,9 +512,9 @@
 	if (ip) {
 		uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
 		in_pcbnotify(&udb, sa, uh->uh_dport, ip->ip_src, uh->uh_sport,
-			cmd, udp_notify);
+			cmd, udp_notify, 0);
 	} else
-		in_pcbnotify(&udb, sa, 0, zeroin_addr, 0, cmd, udp_notify);
+		in_pcbnotify(&udb, sa, 0, zeroin_addr, 0, cmd, udp_notify, 0);
 }
 
 static int

--4Ckj6UjgE2iN1+kY--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001217234119.A90024>