diff options
author | darrenr <darrenr@FreeBSD.org> | 2008-07-24 12:35:05 +0000 |
---|---|---|
committer | darrenr <darrenr@FreeBSD.org> | 2008-07-24 12:35:05 +0000 |
commit | 49ad2adb91673def2dfa0f293612e2de5e3a29af (patch) | |
tree | fbe3003abde766264fafdbbd7e484eafc5be4ad5 /sys/contrib | |
parent | 308672b0059651d854c35e673c94d0f76d84c25f (diff) | |
download | FreeBSD-src-49ad2adb91673def2dfa0f293612e2de5e3a29af.zip FreeBSD-src-49ad2adb91673def2dfa0f293612e2de5e3a29af.tar.gz |
2020447 IPFilter's NAT can undo name server random port selection
Approved by: darrenr
MFC after: 1 week
Security: CERT VU#521769
Diffstat (limited to 'sys/contrib')
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_compat.h | 14 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_fil.h | 6 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_nat.c | 15 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_nat.h | 4 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_state.c | 18 |
5 files changed, 51 insertions, 6 deletions
diff --git a/sys/contrib/ipfilter/netinet/ip_compat.h b/sys/contrib/ipfilter/netinet/ip_compat.h index 97c9d7e..daf824c 100644 --- a/sys/contrib/ipfilter/netinet/ip_compat.h +++ b/sys/contrib/ipfilter/netinet/ip_compat.h @@ -204,6 +204,8 @@ typedef unsigned int u_32_t; # define U_32_T 1 # ifdef _KERNEL +# define NEED_LOCAL_RAND 1 +# define ipf_random arc4random # define KRWLOCK_T krwlock_t # define KMUTEX_T kmutex_t @@ -334,6 +336,7 @@ typedef mblk_t mb_t; typedef struct uio uio_t; # endif typedef int ioctlcmd_t; +typedef uint8_t u_int8_t; # define OS_RECOGNISED 1 @@ -564,6 +567,8 @@ typedef struct { # endif # ifdef _KERNEL +# define NEED_LOCAL_RAND 1 +# define ipf_random arc4random # define ATOMIC_INC(x) { MUTEX_ENTER(&ipf_rw); \ (x)++; MUTEX_EXIT(&ipf_rw); } # define ATOMIC_DEC(x) { MUTEX_ENTER(&ipf_rw); \ @@ -660,6 +665,8 @@ typedef struct mbuf mb_t; # include <sys/sysmacros.h> # ifdef _KERNEL +# define NEED_LOCAL_RAND 1 +# define ipf_random arc4random # define KMUTEX_T simple_lock_data_t # define KRWLOCK_T lock_data_t # include <net/net_globals.h> @@ -781,6 +788,8 @@ typedef unsigned int u_32_t; typedef char * caddr_t; # endif +# define ipf_random arc4random + # ifdef _KERNEL # if (__NetBSD_Version__ >= 399001400) # define KMALLOCS(a, b, c) (a) = (b)malloc((c), _M_IPF, M_NOWAIT) @@ -820,6 +829,11 @@ typedef u_int32_t u_32_t; /* F R E E B S D */ /* ----------------------------------------------------------------------- */ #ifdef __FreeBSD__ +# if (__FreeBSD_version < 400000) +# define NEED_LOCAL_RAND 1 +# else +# define ipf_random arc4random +# endif # if defined(_KERNEL) # if (__FreeBSD_version >= 500000) # include "opt_bpf.h" diff --git a/sys/contrib/ipfilter/netinet/ip_fil.h b/sys/contrib/ipfilter/netinet/ip_fil.h index 353328c..0cd84b9 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.h +++ b/sys/contrib/ipfilter/netinet/ip_fil.h @@ -1523,6 +1523,12 @@ extern void ipf_freetoken __P((ipftoken_t *)); extern int ipf_deltoken __P((int,int, void *)); extern int ipfsync __P((void)); extern int ipf_genericiter __P((void *, int, void *)); +#ifndef ipf_random +extern u_32_t ipf_random __P((void)); +#endif +#ifdef NEED_LOCAL_RAND +extern void ipf_rand_push __P((void *, int)); +#endif extern int fr_running; extern u_long fr_frouteok[2]; diff --git a/sys/contrib/ipfilter/netinet/ip_nat.c b/sys/contrib/ipfilter/netinet/ip_nat.c index a696321..8b227e0 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.c +++ b/sys/contrib/ipfilter/netinet/ip_nat.c @@ -1678,6 +1678,9 @@ int logtype; if (logtype != 0 && nat_logging != 0) nat_log(nat, logtype); +#if defined(NEED_LOCAL_RAND) && defined(_KERNEL) + ipf_rand_push(nat, sizeof(*nat)); +#endif /* * Take it as a general indication that all the pointers are set if @@ -2029,7 +2032,13 @@ natinfo_t *ni; /* * Standard port translation. Select next port. */ - port = htons(np->in_pnext++); + if (np->in_flags & IPN_SEQUENTIAL) { + port = htons(np->in_pnext); + } else { + port = ipf_random() % (ntohs(np->in_pmax) - + ntohs(np->in_pmin)); + } + np->in_pnext++; if (np->in_pnext > ntohs(np->in_pmax)) { np->in_pnext = ntohs(np->in_pmin); @@ -3793,7 +3802,7 @@ u_32_t *passp; READ_ENTER(&ipf_nat); - if ((fin->fin_p == IPPROTO_ICMP) && !(nflags & IPN_ICMPQUERY) && + if (((fin->fin_flx & FI_ICMPERR) != 0) && (nat = nat_icmperror(fin, &nflags, NAT_OUTBOUND))) /*EMPTY*/; else if ((fin->fin_flx & FI_FRAG) && (nat = fr_nat_knownfrag(fin))) @@ -4088,7 +4097,7 @@ u_32_t *passp; READ_ENTER(&ipf_nat); - if ((fin->fin_p == IPPROTO_ICMP) && !(nflags & IPN_ICMPQUERY) && + if (((fin->fin_flx & FI_ICMPERR) != 0) && (nat = nat_icmperror(fin, &nflags, NAT_INBOUND))) /*EMPTY*/; else if ((fin->fin_flx & FI_FRAG) && (nat = fr_nat_knownfrag(fin))) diff --git a/sys/contrib/ipfilter/netinet/ip_nat.h b/sys/contrib/ipfilter/netinet/ip_nat.h index 3020eb6..c8581ef 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.h +++ b/sys/contrib/ipfilter/netinet/ip_nat.h @@ -256,9 +256,11 @@ typedef struct ipnat { #define IPN_FIXEDDPORT 0x200000 #define IPN_FINDFORWARD 0x400000 #define IPN_IN 0x800000 +#define IPN_SEQUENTIAL 0x1000000 #define IPN_USERFLAGS (IPN_TCPUDP|IPN_AUTOPORTMAP|IPN_IPRANGE|IPN_SPLIT|\ IPN_ROUNDR|IPN_FILTER|IPN_NOTSRC|IPN_NOTDST|\ - IPN_FRAG|IPN_STICKY|IPN_FIXEDDPORT|IPN_ICMPQUERY) + IPN_FRAG|IPN_STICKY|IPN_FIXEDDPORT|IPN_ICMPQUERY|\ + IPN_SEQUENTIAL) /* * Values for in_redir diff --git a/sys/contrib/ipfilter/netinet/ip_state.c b/sys/contrib/ipfilter/netinet/ip_state.c index aa9192a..6c8b158 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.c +++ b/sys/contrib/ipfilter/netinet/ip_state.c @@ -195,6 +195,9 @@ ipstate_t *ips_list = NULL; /* ------------------------------------------------------------------------ */ int fr_stateinit() { +#if defined(NEED_LOCAL_RAND) || !defined(_KERNEL) + struct timeval tv; +#endif int i; KMALLOCS(ips_table, ipstate_t **, fr_statesize * sizeof(ipstate_t *)); @@ -205,20 +208,27 @@ int fr_stateinit() KMALLOCS(ips_seed, u_long *, fr_statesize * sizeof(*ips_seed)); if (ips_seed == NULL) return -2; +#if defined(NEED_LOCAL_RAND) || !defined(_KERNEL) + tv.tv_sec = 0; + GETKTIME(&tv); +#endif for (i = 0; i < fr_statesize; i++) { /* * XXX - ips_seed[X] should be a random number of sorts. */ -#if (__FreeBSD_version >= 400000) +#if !defined(NEED_LOCAL_RAND) && defined(_KERNEL) ips_seed[i] = arc4random(); #else ips_seed[i] = ((u_long)ips_seed + i) * fr_statesize; - ips_seed[i] ^= 0xa5a55a5a; + ips_seed[i] += tv.tv_sec; ips_seed[i] *= (u_long)ips_seed; ips_seed[i] ^= 0x5a5aa5a5; ips_seed[i] *= fr_statemax; #endif } +#if defined(NEED_LOCAL_RAND) && defined(_KERNEL) + ipf_rand_push(ips_seed, fr_statesize * sizeof(*ips_seed)); +#endif /* fill icmp reply type table */ for (i = 0; i <= ICMP_MAXTYPE; i++) @@ -3028,6 +3038,10 @@ int why; (void) fr_derefrule(&is->is_rule); } +#if defined(NEED_LOCAL_RAND) && defined(_KERNEL) + ipf_rand_push(is, sizeof(*is)); +#endif + MUTEX_DESTROY(&is->is_lock); KFREE(is); ips_num--; |