in-kernel ftp proxy. See sbin/ipf/HISTORY for details.
-# $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"
-/* $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>
-/* $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__
-/* $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.
#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[];
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
-/* $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.
*/
#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
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
-/* $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.
* 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__
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];
-/* $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.
-/* $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
#endif
#define isdigit(x) ((x) >= '0' && (x) <= '9')
+#define isupper(x) ((unsigned)((x) - 'A') <= 'Z' - 'A')
#define IPF_FTP_PROXY
#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;
/*
}
+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),
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;
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
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);
* 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
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;
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;
-/* $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.
*/
#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)
}
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) &&
-/* $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.
* 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 */
-/* $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.
* 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)
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,
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;
}
-/* $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.
* 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__
#define APR_DELETE 1
+/*
+ * For the ftp proxy.
+ */
+typedef struct ftpinfo {
+ u_int ftp_passok;
+} ftpinfo_t;
+
/*
* Real audio proxy structure and #defines
*/
-/* $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;
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;
}
-/* $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.
#ifndef __IPL_H__
#define __IPL_H__
-#define IPL_VERSION "IP Filter: v3.3.11"
+#define IPL_VERSION "IP Filter: v3.3.12"
#endif