From owner-svn-src-head@FreeBSD.ORG Fri Jan 9 16:02:20 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 30CB0106564A; Fri, 9 Jan 2009 16:02:20 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 1ED298FC0A; Fri, 9 Jan 2009 16:02:20 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n09G2Jme061170; Fri, 9 Jan 2009 16:02:19 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n09G2Jj1061164; Fri, 9 Jan 2009 16:02:19 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <200901091602.n09G2Jj1061164@svn.freebsd.org> From: Adrian Chadd Date: Fri, 9 Jan 2009 16:02:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r186955 - in head/sys: conf netinet X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 09 Jan 2009 16:02:20 -0000 Author: adrian Date: Fri Jan 9 16:02:19 2009 New Revision: 186955 URL: http://svn.freebsd.org/changeset/base/186955 Log: Implement a new IP option (not compiled/enabled by default) to allow applications to specify a non-local IP address when bind()'ing a socket to a local endpoint. This allows applications to spoof the client IP address of connections if (obviously!) they somehow are able to receive the traffic normally destined to said clients. This patch doesn't include any changes to ipfw or the bridging code to redirect the client traffic through the PCB checks so TCP gets a shot at it. The normal behaviour is that packets with a non-local destination IP address are not handled locally. This can be dealth with some IPFW hackery; modifications to IPFW to make this less hacky will occur in subsequent commmits. Thanks to Julian Elischer and others at Ironport. This work was approved and donated before Cisco acquired them. Obtained from: Julian Elischer and others MFC after: 2 weeks Modified: head/sys/conf/NOTES head/sys/conf/options head/sys/netinet/in.h head/sys/netinet/in_pcb.c head/sys/netinet/in_pcb.h head/sys/netinet/ip_output.c Modified: head/sys/conf/NOTES ============================================================================== --- head/sys/conf/NOTES Fri Jan 9 15:13:46 2009 (r186954) +++ head/sys/conf/NOTES Fri Jan 9 16:02:19 2009 (r186955) @@ -633,6 +633,14 @@ options ALTQ_PRIQ # Priority Queueing options ALTQ_NOPCC # Required if the TSC is unusable options ALTQ_DEBUG +# IP optional behaviour. +# IP_NONLOCALBIND disables the check that bind() usually makes that the +# Address is one that is assigned to an interface on this machine. +# It allows transparent proxies to pretend to be other machines. +# How the packet GET to that machine is a problem solved elsewhere, +# smart routers, ipfw fwd, etc. +options IP_NONLOCALBIND #Allow impersonation for proxies. + # netgraph(4). Enable the base netgraph code with the NETGRAPH option. # Individual node types can be enabled with the corresponding option # listed below; however, this is not strictly necessary as netgraph Modified: head/sys/conf/options ============================================================================== --- head/sys/conf/options Fri Jan 9 15:13:46 2009 (r186954) +++ head/sys/conf/options Fri Jan 9 16:02:19 2009 (r186955) @@ -392,6 +392,7 @@ IPFIREWALL_VERBOSE opt_ipfw.h IPFIREWALL_VERBOSE_LIMIT opt_ipfw.h IPSEC opt_ipsec.h IPSEC_DEBUG opt_ipsec.h +IP_NONLOCALBIND opt_inet.h IPSEC_FILTERTUNNEL opt_ipsec.h IPSTEALTH IPX Modified: head/sys/netinet/in.h ============================================================================== --- head/sys/netinet/in.h Fri Jan 9 15:13:46 2009 (r186954) +++ head/sys/netinet/in.h Fri Jan 9 16:02:19 2009 (r186955) @@ -441,6 +441,7 @@ __END_DECLS #define IP_FAITH 22 /* bool; accept FAITH'ed connections */ #define IP_ONESBCAST 23 /* bool: send all-ones broadcast */ +#define IP_NONLOCALOK 24 /* allow bind to spoof other machines */ #define IP_FW_TABLE_ADD 40 /* add entry */ #define IP_FW_TABLE_DEL 41 /* delete entry */ Modified: head/sys/netinet/in_pcb.c ============================================================================== --- head/sys/netinet/in_pcb.c Fri Jan 9 15:13:46 2009 (r186954) +++ head/sys/netinet/in_pcb.c Fri Jan 9 16:02:19 2009 (r186955) @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include "opt_ddb.h" +#include "opt_inet.h" #include "opt_ipsec.h" #include "opt_inet6.h" #include "opt_mac.h" @@ -346,7 +347,11 @@ in_pcbbind_setup(struct inpcb *inp, stru } else if (sin->sin_addr.s_addr != INADDR_ANY) { sin->sin_port = 0; /* yech... */ bzero(&sin->sin_zero, sizeof(sin->sin_zero)); - if (ifa_ifwithaddr((struct sockaddr *)sin) == 0) + if ( +#if defined(IP_NONLOCALBIND) + ((inp->inp_flags & INP_NONLOCALOK) == 0) && +#endif + (ifa_ifwithaddr((struct sockaddr *)sin) == 0)) return (EADDRNOTAVAIL); } laddr = sin->sin_addr; Modified: head/sys/netinet/in_pcb.h ============================================================================== --- head/sys/netinet/in_pcb.h Fri Jan 9 15:13:46 2009 (r186954) +++ head/sys/netinet/in_pcb.h Fri Jan 9 16:02:19 2009 (r186955) @@ -411,6 +411,8 @@ void inp_4tuple_get(struct inpcb *inp, #define INP_FAITH 0x200 /* accept FAITH'ed connections */ #define INP_RECVTTL 0x400 /* receive incoming IP TTL */ #define INP_DONTFRAG 0x800 /* don't fragment packet */ +#define INP_NONLOCALOK 0x1000 /* Allow bind to spoof any address */ + /* - requires options IP_NONLOCALBIND */ #define IN6P_IPV6_V6ONLY 0x008000 /* restrict AF_INET6 socket for v6 */ Modified: head/sys/netinet/ip_output.c ============================================================================== --- head/sys/netinet/ip_output.c Fri Jan 9 15:13:46 2009 (r186954) +++ head/sys/netinet/ip_output.c Fri Jan 9 16:02:19 2009 (r186955) @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include "opt_ipfw.h" +#include "opt_inet.h" #include "opt_ipsec.h" #include "opt_mac.h" #include "opt_mbuf_stress_test.h" @@ -95,6 +96,12 @@ SYSCTL_INT(_net_inet_ip, OID_AUTO, mbuf_ &mbuf_frag_size, 0, "Fragment outgoing mbufs to this size"); #endif +#if defined(IP_NONLOCALBIND) +static int ip_nonlocalok = 0; +SYSCTL_INT(_net_inet_ip, OID_AUTO, nonlocalok, + CTLFLAG_RW|CTLFLAG_SECURE, &ip_nonlocalok, 0, ""); +#endif + static void ip_mloopback (struct ifnet *, struct mbuf *, struct sockaddr_in *, int); @@ -866,6 +873,13 @@ ip_ctloutput(struct socket *so, struct s return (error); } +#if defined(IP_NONLOCALBIND) + case IP_NONLOCALOK: + if (! ip_nonlocalok) { + error = ENOPROTOOPT; + break; + } +#endif case IP_TOS: case IP_TTL: case IP_MINTTL: @@ -937,6 +951,11 @@ ip_ctloutput(struct socket *so, struct s case IP_DONTFRAG: OPTSET(INP_DONTFRAG); break; +#if defined(IP_NONLOCALBIND) + case IP_NONLOCALOK: + OPTSET(INP_NONLOCALOK); + break; +#endif } break; #undef OPTSET