Update to ipf 3.3.12. Most fixes relate to hardening of
authorkjell <kjell@openbsd.org>
Wed, 5 Apr 2000 05:35:27 +0000 (05:35 +0000)
committerkjell <kjell@openbsd.org>
Wed, 5 Apr 2000 05:35:27 +0000 (05:35 +0000)
in-kernel ftp proxy. See sbin/ipf/HISTORY for details.

14 files changed:
sbin/ipf/HISTORY
sbin/ipf/ifaddr.c
sbin/ipf/ifaddr.h
sbin/ipf/parse.c
sys/netinet/ip_fil.c
sys/netinet/ip_fil.h
sys/netinet/ip_fil_compat.h
sys/netinet/ip_ftp_pxy.c
sys/netinet/ip_nat.c
sys/netinet/ip_nat.h
sys/netinet/ip_proxy.c
sys/netinet/ip_proxy.h
sys/netinet/ip_raudio_pxy.c
sys/netinet/ipl.h

index 84b5927..bd61b94 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: HISTORY,v 1.5 2000/03/13 23:40:19 kjell Exp $
+#      $OpenBSD: HISTORY,v 1.6 2000/04/05 05:35:28 kjell Exp $
 #
 # NOTE: Quite a few patches and suggestions come from other sources, to whom
 #       I'm greatly indebted, even if no names are mentioned.
 # and especially those who have found the time to port IP Filter to new
 # platforms.
 #
+3.3.12 16/03/2000 - Released
+
+tighten up ftp proxy behaviour.  sigh.  yuck.  hate.
+
+fix bug in range check for NAT where the last IP# was not used.
+
+fix problem with icmp codes > 127 in filter rules caused bad things to
+happen and in particular, where #18 caused the rule to be printed
+erroneously.
+
+fix bug with the spl level not being reset when returning EIO from
+iplioctl due to ipfilter not being initialized yet.
+
 3.3.11 04/03/2000 - Released
 
 make "or-block" work with lines that start with "log"
index e34116d..3f162c3 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ifaddr.c,v 1.4 2000/03/13 23:40:19 kjell Exp $ */
+/* $OpenBSD: ifaddr.c,v 1.5 2000/04/05 05:35:28 kjell Exp $ */
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
index 8810aac..bb882dc 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ifaddr.h,v 1.4 2000/03/13 23:40:19 kjell Exp $ */
+/* $OpenBSD: ifaddr.h,v 1.5 2000/04/05 05:35:28 kjell Exp $ */
 
 #ifndef        __IFADDR_H__
 #define        __IFADDR_H__
index 8196186..8b3e04f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: parse.c,v 1.33 2000/03/13 23:40:19 kjell Exp $        */
+/*     $OpenBSD: parse.c,v 1.34 2000/04/05 05:35:28 kjell Exp $        */
 
 /*
  * Copyright (C) 1993-1998 by Darren Reed.
@@ -43,7 +43,7 @@
 
 #if !defined(lint)
 static const char sccsid[] = "@(#)parse.c      1.44 6/5/96 (C) 1993-1996 Darren Reed";
-static const char rcsid[] = "@(#)$IPFilter: parse.c,v 2.1.2.11 2000/03/04 05:19:25 darrenr Exp $";
+static const char rcsid[] = "@(#)$IPFilter: parse.c,v 2.1.2.12 2000/03/08 11:43:55 darrenr Exp $";
 #endif
 
 extern struct  ipopt_names     ionames[], secclass[];
@@ -1560,7 +1560,7 @@ struct    frentry *fp;
                type = ntohs(fp->fr_icmp);
                code = type & 0xff;
                type /= 256;
-               if (type < (sizeof(icmptypes) / sizeof(char *)) &&
+               if (type < (sizeof(icmptypes) / sizeof(char *) - 1) &&
                    icmptypes[type])
                        printf(" icmp-type %s", icmptypes[type]);
                else
index 42370ca..ce1a343 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_fil.c,v 1.32 2000/03/13 23:40:17 kjell Exp $       */
+/*     $OpenBSD: ip_fil.c,v 1.33 2000/04/05 05:35:27 kjell Exp $       */
 
 /*
  * Copyright (C) 1993-1998 by Darren Reed.
@@ -9,7 +9,7 @@
  */
 #if !defined(lint)
 static const char sccsid[] = "@(#)ip_fil.c     2.41 6/5/96 (C) 1993-1995 Darren Reed";
-static const char rcsid[] = "@(#)$IPFilter: ip_fil.c,v 2.4.2.18 2000/02/22 11:40:06 darrenr Exp $";
+static const char rcsid[] = "@(#)$IPFilter: ip_fil.c,v 2.4.2.19 2000/03/07 14:41:39 darrenr Exp $";
 #endif
 
 #ifndef        SOLARIS
@@ -472,19 +472,23 @@ int mode;
        SPL_NET(s);
 
        if (unit == IPL_LOGNAT) {
-               if (!fr_running)
-                       return EIO;
-               error = nat_ioctl(data, cmd, mode);
+               if (fr_running)
+                       error = nat_ioctl(data, cmd, mode);
+               else
+                       error = EIO;
                SPL_X(s);
                return error;
        }
+
        if (unit == IPL_LOGSTATE) {
-               if (!fr_running)
-                       return EIO;
-               error = fr_state_ioctl(data, cmd, mode);
+               if (fr_running)
+                       error = fr_state_ioctl(data, cmd, mode);
+               else
+                       error = EIO;
                SPL_X(s);
                return error;
        }
+
        switch (cmd) {
        case FIONREAD :
 #ifdef IPFILTER_LOG
index 0659077..9a0dcd9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_fil.h,v 1.17 2000/03/13 23:40:17 kjell Exp $       */
+/*     $OpenBSD: ip_fil.h,v 1.18 2000/04/05 05:35:27 kjell Exp $       */
 
 /*
  * Copyright (C) 1993-1998 by Darren Reed.
@@ -8,7 +8,7 @@
  * to the original author and the contributors.
  *
  * @(#)ip_fil.h        1.35 6/5/96
- * $IPFilter: ip_fil.h,v 2.3.2.8 2000/02/23 11:16:36 darrenr Exp $
+ * $IPFilter: ip_fil.h,v 2.3.2.9 2000/03/08 11:43:30 darrenr Exp $
  */
 
 #ifndef        __IP_FIL_H__
@@ -187,7 +187,7 @@ typedef     struct  frentry {
        u_short fr_skip;        /* # of rules to skip */
        u_short fr_loglevel;    /* syslog log facility + priority */
        int     (*fr_func) __P((int, ip_t *, fr_info_t *));     /* call this function */
-       char    fr_icode;       /* return ICMP code */
+       u_char  fr_icode;       /* return ICMP code */
        char    fr_ifname[IFNAMSIZ];
 #if BSD >= 199306
        char    fr_oifname[IFNAMSIZ];
index 0ad32f2..a23220e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_fil_compat.h,v 1.14 2000/03/13 23:40:18 kjell Exp $        */
+/*     $OpenBSD: ip_fil_compat.h,v 1.15 2000/04/05 05:35:27 kjell Exp $        */
 
 /*
  * Copyright (C) 1993-1998 by Darren Reed.
index 8080ad9..ab947e7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_ftp_pxy.c,v 1.8 2000/03/13 23:40:18 kjell Exp $    */
+/*     $OpenBSD: ip_ftp_pxy.c,v 1.9 2000/04/05 05:35:27 kjell Exp $    */
 
 /*
  * Simple FTP transparent proxy for in-kernel use.  For use with the NAT
@@ -9,6 +9,7 @@ extern  kmutex_t        ipf_rw;
 #endif
 
 #define        isdigit(x)      ((x) >= '0' && (x) <= '9')
+#define        isupper(x)      ((unsigned)((x) - 'A') <= 'Z' - 'A')
 
 #define        IPF_FTP_PROXY
 
@@ -16,17 +17,23 @@ extern      kmutex_t        ipf_rw;
 #define        IPF_MAXPORTLEN  30
 #define        IPF_MIN227LEN   39
 #define        IPF_MAX227LEN   51
+#define        IPF_FTPBUFSZ    MAX(68,IPF_MAX227LEN)   /* This *MUST* be >= 51! */
+                       /* 68 is chosen as the minimum datagram size for */
+                       /* an unfragmented packet */
 
 
 int ippr_ftp_init __P((void));
+int ippr_ftp_new __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
 int ippr_ftp_out __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
 int ippr_ftp_in __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
 int ippr_ftp_portmsg __P((fr_info_t *, ip_t *, nat_t *));
 int ippr_ftp_pasvmsg __P((fr_info_t *, ip_t *, nat_t *));
+int ippr_ftp_complete __P((char *, size_t));
 
 u_short ipf_ftp_atoi __P((char **));
 
 static frentry_t       natfr;
+int    ippr_ftp_pasvonly = 0;
 
 
 /*
@@ -41,6 +48,90 @@ int ippr_ftp_init()
 }
 
 
+int ippr_ftp_complete(buf, len)
+char *buf;
+size_t len;
+{
+       register char *s, c;
+       register size_t i;
+
+       if (len < 5)
+               return -1;
+       s = buf;
+       c = *s++;
+       i = len - 1;
+
+       if (isdigit(c)) {
+               c = *s++;
+               i--;
+               if (isdigit(c)) {
+                       c = *s++;
+                       i--;
+                       if (isdigit(c)) {
+                               c = *s++;
+                               i--;
+                               if (c != '-' && c != ' ')
+                                       return -1;
+                       } else
+                               return -1;
+               } else
+                       return -1;
+       } else if (isupper(c)) {
+               c = *s++;
+               i--;
+               if (isupper(c)) {
+                       c = *s++;
+                       i--;
+                       if (isupper(c)) {
+                               c = *s++;
+                               i--;
+                               if (isupper(c)) {
+                                       c = *s++;
+                                       i--;
+                                       if (c != ' ')
+                                               return -1;
+                               } else
+                                       return -1;
+                       } else
+                               return -1;
+               } else
+                       return -1;
+       } else
+               return -1;
+
+       for (; i && (c = *s); i--, s++) {
+               if ((c == '\r') && (i != 2))
+                       return -1;
+               if ((c == '\n') && (i != 1))
+                       return -1;
+               else if ((i == 2) && (c != '\r'))
+                       return -1;
+               else if ((i == 1) && (c != '\n'))
+                       return -1;
+       }
+       return i;
+}
+
+
+int ippr_ftp_new(fin, ip, aps, nat)
+fr_info_t *fin;
+ip_t *ip;
+ap_session_t *aps;
+nat_t *nat;
+{
+       ftpinfo_t *ftp;
+
+       KMALLOC(ftp, ftpinfo_t *);
+       if (ftp == NULL)
+               return -1;
+       aps->aps_data = ftp;
+       aps->aps_psiz = sizeof(ftpinfo_t);
+
+       ftp->ftp_passok = 0;
+       return 0;
+}
+
+
 /*
  * ipf_ftp_atoi - implement a version of atoi which processes numbers in
  * pairs separated by commas (which are expected to be in the range 0 - 255),
@@ -75,13 +166,14 @@ fr_info_t *fin;
 ip_t *ip;
 nat_t *nat;
 {
-       char portbuf[IPF_MAXPORTLEN + 1], newbuf[IPF_MAXPORTLEN + 1], *s;
+       char portbuf[IPF_FTPBUFSZ], newbuf[IPF_FTPBUFSZ], *s;
        tcphdr_t *tcp, tcph, *tcp2 = &tcph;
        size_t nlen = 0, dlen, olen;
        u_short a5, a6, sp, dp;
        u_int a1, a2, a3, a4;
        struct in_addr swip;
        int off, inc = 0;
+       ftpinfo_t *ftp;
        fr_info_t fi;
        nat_t *ipn;
        mb_t *m;
@@ -110,7 +202,30 @@ nat_t *nat;
                return 0;
        portbuf[sizeof(portbuf) - 1] = '\0';
        *newbuf = '\0';
-       if (!strncmp(portbuf, "PORT ", 5)) { 
+
+       /*
+        * Check that a user is progressing through the login ok.
+        */
+       if (ippr_ftp_complete(portbuf, dlen))
+               return 0;
+       ftp = nat->nat_aps->aps_data;
+       switch (ftp->ftp_passok)
+       {
+       case 0 :
+               if (!strncmp(portbuf, "USER ", 5))
+                       ftp->ftp_passok = 1;
+               break;
+       case 2 :
+               if (!strncmp(portbuf, "PASS ", 5))
+                       ftp->ftp_passok = 3;
+               break;
+       }
+       if (ftp->ftp_passok != 4)
+               return 0;
+       /*
+        * Check for client sending out PORT message.
+        */
+       if (!ippr_ftp_pasvonly && !strncmp(portbuf, "PORT ", 5)) { 
                if (dlen < IPF_MINPORTLEN)
                        return 0;
        } else
@@ -165,6 +280,7 @@ nat_t *nat;
        a4 = a1 & 0xff;
        a1 >>= 24;
        olen = s - portbuf;
+       /* DO NOT change this to sprintf! */
        (void) sprintf(newbuf, "%s %u,%u,%u,%u,%u,%u\r\n",
                       "PORT", a1, a2, a3, a4, a5, a6);
 
@@ -224,6 +340,12 @@ nat_t *nat;
         * other way.
         */
        sp = htons(a5 << 8 | a6);
+       /*
+        * Don't allow the PORT command to specify a port < 1024 due to
+        * security crap.
+        */
+       if (ntohs(sp) < 1024)
+               return 0;
        /*
         * The server may not make the connection back from port 20, but
         * it is the most likely so use it here to check for a conflicting
@@ -270,12 +392,13 @@ fr_info_t *fin;
 ip_t *ip;
 nat_t *nat;
 {
-       char portbuf[IPF_MAX227LEN + 1], newbuf[IPF_MAX227LEN + 1], *s;
+       char portbuf[IPF_FTPBUFSZ], newbuf[IPF_FTPBUFSZ], *s;
        int off, olen, dlen, nlen = 0, inc = 0;
        tcphdr_t tcph, *tcp2 = &tcph;
        struct in_addr swip, swip2;
        u_short a5, a6, dp, sp;
        u_int a1, a2, a3, a4;
+       ftpinfo_t *ftp;
        tcphdr_t *tcp;
        fr_info_t fi;
        nat_t *ipn;
@@ -305,6 +428,35 @@ nat_t *nat;
        portbuf[sizeof(portbuf) - 1] = '\0';
        *newbuf = '\0';
 
+       /*
+        * Check that a user is progressing through the login ok.
+        * Don't put the switch in one common function because one side
+        * should only see numeric responses and the other commands.
+        */
+       if (ippr_ftp_complete(portbuf, dlen))
+               return 0;
+       ftp = nat->nat_aps->aps_data;
+       switch (ftp->ftp_passok)
+       {
+       case 1 :
+               if (!strncmp(portbuf, "331", 3))
+                       ftp->ftp_passok = 2;
+               else if (!strncmp(portbuf, "520", 3))
+                       ftp->ftp_passok = 0;
+               break;
+       case 3 :
+               if (!strncmp(portbuf, "230", 3))
+                       ftp->ftp_passok = 4;
+               break;
+       default :
+               break;
+       }
+
+       if (ftp->ftp_passok != 4)
+               return 0;
+       /*
+        * Check for PASV reply message.
+        */
        if (!strncmp(portbuf, "227 ", 4)) {
                if (dlen < IPF_MIN227LEN)
                        return 0;
index 49b1912..d0237d4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_nat.c,v 1.28 2000/03/13 23:40:18 kjell Exp $       */
+/*     $OpenBSD: ip_nat.c,v 1.29 2000/04/05 05:35:27 kjell Exp $       */
 
 /*
  * Copyright (C) 1995-1998 by Darren Reed.
@@ -11,7 +11,7 @@
  */
 #if !defined(lint)
 static const char sccsid[] = "@(#)ip_nat.c     1.11 6/5/96 (C) 1995 Darren Reed";
-static const char rcsid[] = "@(#)$IPFilter: ip_nat.c,v 2.2.2.12 2000/01/24 12:43:40 darrenr Exp $";
+static const char rcsid[] = "@(#)$IPFilter: ip_nat.c,v 2.2.2.13 2000/03/08 14:17:26 darrenr Exp $";
 #endif
 
 #if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL)
@@ -859,7 +859,7 @@ int direction;
                        }
 
                        if (np->in_flags & IPN_RANGE) {
-                               if (np->in_nip >= ntohl(np->in_outmsk))
+                               if (np->in_nip > ntohl(np->in_outmsk))
                                        np->in_nip = ntohl(np->in_outip);
                        } else {
                                if ((np->in_outmsk != 0xffffffff) &&
index 09fb932..9d12629 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_nat.h,v 1.16 2000/03/13 23:40:18 kjell Exp $       */
+/*     $OpenBSD: ip_nat.h,v 1.17 2000/04/05 05:35:27 kjell Exp $       */
 
 /*
  * Copyright (C) 1995-1998 by Darren Reed.
@@ -8,7 +8,7 @@
  * to the original author and the contributors.
  *
  * @(#)ip_nat.h        1.5 2/4/96
- * $IPFilter: ip_nat.h,v 2.1.2.3 2000/01/24 12:44:24 darrenr Exp $
+ * $IPFilter: ip_nat.h,v 2.1.2.4 2000/03/15 13:57:03 darrenr Exp $
  */
 
 #ifndef        __IP_NAT_H__
 
 #define        DEF_NAT_AGE     1200     /* 10 minutes (600 seconds) */
 
+struct ap_session;
+
 typedef        struct  nat     {
        u_long  nat_age;
        int     nat_flags;
        u_32_t  nat_sumd[2];
        u_32_t  nat_ipsumd;
        void    *nat_data;
-       void    *nat_aps;               /* proxy session */
-       frentry_t       *nat_fr;        /* filter rule ptr if appropriate */
+       struct  ap_session      *nat_aps;               /* proxy session */
+       struct  frentry *nat_fr;        /* filter rule ptr if appropriate */
        struct  in_addr nat_inip;
        struct  in_addr nat_outip;
        struct  in_addr nat_oip;        /* other ip */
index bb3f623..2184909 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_proxy.c,v 1.8 2000/03/13 23:40:18 kjell Exp $      */
+/*     $OpenBSD: ip_proxy.c,v 1.9 2000/04/05 05:35:27 kjell Exp $      */
 
 /*
  * Copyright (C) 1997-1998 by Darren Reed.
@@ -8,7 +8,7 @@
  * to the original author and the contributors.
  */
 #if !defined(lint)
-static const char rcsid[] = "@(#)$IPFilter: ip_proxy.c,v 2.2.2.3 2000/02/29 22:47:17 darrenr Exp $";
+static const char rcsid[] = "@(#)$IPFilter: ip_proxy.c,v 2.2.2.4 2000/03/15 13:57:53 darrenr Exp $";
 #endif
 
 #if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL)
@@ -102,8 +102,8 @@ ap_session_t        *ap_sess_tab[AP_SESS_SIZE];
 ap_session_t   *ap_sess_list = NULL;
 aproxy_t       ap_proxies[] = {
 #ifdef IPF_FTP_PROXY
-       { "ftp", (char)IPPROTO_TCP, 0, 0, ippr_ftp_init, NULL, NULL,
-         ippr_ftp_in, ippr_ftp_out },
+       { "ftp", (char)IPPROTO_TCP, 0, 0, ippr_ftp_init, NULL,
+         ippr_ftp_new, ippr_ftp_in, ippr_ftp_out },
 #endif
 #ifdef IPF_RCMD_PROXY
        { "rcmd", (char)IPPROTO_TCP, 0, 0, ippr_rcmd_init, NULL,
@@ -154,16 +154,18 @@ nat_t *nat;
        if (!aps)
                return NULL;
        bzero((char *)aps, sizeof(*aps));
-       aps->aps_next = ap_sess_list;
        aps->aps_p = ip->ip_p;
        aps->aps_data = NULL;
        aps->aps_apr = apr;
        aps->aps_psiz = 0;
-       ap_sess_list = aps;
-       aps->aps_nat = nat;
-       nat->nat_aps = aps;
        if (apr->apr_new != NULL)
-               (void) (*apr->apr_new)(fin, ip, aps, nat);
+               if ((*apr->apr_new)(fin, ip, aps, nat) == -1) {
+                       KFREE(aps);
+                       return NULL;
+               }
+       aps->aps_nat = nat;
+       aps->aps_next = ap_sess_list;
+       ap_sess_list = aps;
        return aps;
 }
 
index 204ca73..f20e8b9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_proxy.h,v 1.7 2000/03/13 23:40:18 kjell Exp $      */
+/*     $OpenBSD: ip_proxy.h,v 1.8 2000/04/05 05:35:27 kjell Exp $      */
 
 /*
  * Copyright (C) 1997-1998 by Darren Reed.
@@ -7,7 +7,7 @@
  * provided that this notice is preserved and due credit is given
  * to the original author and the contributors.
  *
- * $IPFilter: ip_proxy.h,v 2.1.2.2 2000/02/22 11:41:15 darrenr Exp $
+ * $IPFilter: ip_proxy.h,v 2.1.2.3 2000/03/15 13:58:15 darrenr Exp $
  */
 
 #ifndef        __IP_PROXY_H__
@@ -86,6 +86,13 @@ typedef      struct  aproxy  {
 #define        APR_DELETE      1
 
 
+/*
+ * For the ftp proxy.
+ */
+typedef struct  ftpinfo {
+       u_int   ftp_passok;
+} ftpinfo_t;
+
 /*
  * Real audio proxy structure and #defines
  */
index f43e05b..4f1eb26 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_raudio_pxy.c,v 1.6 2000/03/13 23:40:18 kjell Exp $ */
+/*     $OpenBSD: ip_raudio_pxy.c,v 1.7 2000/04/05 05:35:27 kjell Exp $ */
 
 #if SOLARIS && defined(_KERNEL)
 extern kmutex_t        ipf_rw;
@@ -40,12 +40,13 @@ nat_t *nat;
 
 
        KMALLOCS(aps->aps_data, void *, sizeof(raudio_t));
-       if (aps->aps_data != NULL) {
-               bzero(aps->aps_data, sizeof(raudio_t));
-               rap = aps->aps_data;
-               aps->aps_psiz = sizeof(raudio_t);
-               rap->rap_mode = RAP_M_TCP;      /* default is for TCP */
-       }
+       if (aps->aps_data == NULL)
+               return -1;
+
+       bzero(aps->aps_data, sizeof(raudio_t));
+       rap = aps->aps_data;
+       aps->aps_psiz = sizeof(raudio_t);
+       rap->rap_mode = RAP_M_TCP;      /* default is for TCP */
        return 0;
 }
 
index dbde999..50e8ae0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ipl.h,v 1.6 2000/03/13 23:40:18 kjell Exp $   */
+/*     $OpenBSD: ipl.h,v 1.7 2000/04/05 05:35:27 kjell Exp $   */
 
 /*
  * Copyright (C) 1993-1999 by Darren Reed.
@@ -13,6 +13,6 @@
 #ifndef        __IPL_H__
 #define        __IPL_H__
 
-#define        IPL_VERSION     "IP Filter: v3.3.11"
+#define        IPL_VERSION     "IP Filter: v3.3.12"
 
 #endif