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.
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

Reply via email to