- Rename IP_NONLOCALOK IP socket option to IP_BINDANY, to be more consistent
with OpenBSD (and BSD/OS originally). We can't easly do it SOL_SOCKET option as there is no more space for more SOL_SOCKET options, but this option also fits better as an IP socket option, it seems. - Implement this functionality also for IPv6 and RAW IP sockets. - Always compile it in (don't use additional kernel options). - Remove sysctl to turn this functionality on and off. - Introduce new privilege - PRIV_NETINET_BINDANY, which allows to use this functionality (currently only unjail root can use it). Discussed with: julian, adrian, jhb, rwatson, kmacy
This commit is contained in:
parent
2430d82448
commit
f44270e764
@ -639,14 +639,6 @@ options ALTQ_PRIQ # Priority Queueing
|
|||||||
options ALTQ_NOPCC # Required if the TSC is unusable
|
options ALTQ_NOPCC # Required if the TSC is unusable
|
||||||
options ALTQ_DEBUG
|
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.
|
# netgraph(4). Enable the base netgraph code with the NETGRAPH option.
|
||||||
# Individual node types can be enabled with the corresponding option
|
# Individual node types can be enabled with the corresponding option
|
||||||
# listed below; however, this is not strictly necessary as netgraph
|
# listed below; however, this is not strictly necessary as netgraph
|
||||||
|
@ -400,7 +400,6 @@ IPFIREWALL_VERBOSE opt_ipfw.h
|
|||||||
IPFIREWALL_VERBOSE_LIMIT opt_ipfw.h
|
IPFIREWALL_VERBOSE_LIMIT opt_ipfw.h
|
||||||
IPSEC opt_ipsec.h
|
IPSEC opt_ipsec.h
|
||||||
IPSEC_DEBUG opt_ipsec.h
|
IPSEC_DEBUG opt_ipsec.h
|
||||||
IP_NONLOCALBIND opt_inet.h
|
|
||||||
IPSEC_FILTERTUNNEL opt_ipsec.h
|
IPSEC_FILTERTUNNEL opt_ipsec.h
|
||||||
IPSTEALTH
|
IPSTEALTH
|
||||||
IPX
|
IPX
|
||||||
|
@ -441,8 +441,7 @@ __END_DECLS
|
|||||||
#define IP_FAITH 22 /* bool; accept FAITH'ed connections */
|
#define IP_FAITH 22 /* bool; accept FAITH'ed connections */
|
||||||
|
|
||||||
#define IP_ONESBCAST 23 /* bool: send all-ones broadcast */
|
#define IP_ONESBCAST 23 /* bool: send all-ones broadcast */
|
||||||
#define IP_NONLOCALOK 24 /* bool: allow bind to spoof non-local addresses;
|
#define IP_BINDANY 24 /* bool: allow bind to any address */
|
||||||
requires kernel compile option IP_NONLOCALBIND */
|
|
||||||
|
|
||||||
#define IP_FW_TABLE_ADD 40 /* add entry */
|
#define IP_FW_TABLE_ADD 40 /* add entry */
|
||||||
#define IP_FW_TABLE_DEL 41 /* delete entry */
|
#define IP_FW_TABLE_DEL 41 /* delete entry */
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include "opt_ddb.h"
|
#include "opt_ddb.h"
|
||||||
#include "opt_inet.h"
|
|
||||||
#include "opt_ipsec.h"
|
#include "opt_ipsec.h"
|
||||||
#include "opt_inet6.h"
|
#include "opt_inet6.h"
|
||||||
#include "opt_mac.h"
|
#include "opt_mac.h"
|
||||||
@ -357,14 +356,11 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
|
|||||||
bzero(&sin->sin_zero, sizeof(sin->sin_zero));
|
bzero(&sin->sin_zero, sizeof(sin->sin_zero));
|
||||||
/*
|
/*
|
||||||
* Is the address a local IP address?
|
* Is the address a local IP address?
|
||||||
* If INP_NONLOCALOK is set, then the socket may be bound
|
* If INP_BINDANY is set, then the socket may be bound
|
||||||
* to any endpoint address, local or not.
|
* to any endpoint address, local or not.
|
||||||
*/
|
*/
|
||||||
if (
|
if ((inp->inp_flags & INP_BINDANY) == 0 &&
|
||||||
#if defined(IP_NONLOCALBIND)
|
ifa_ifwithaddr((struct sockaddr *)sin) == NULL)
|
||||||
((inp->inp_flags & INP_NONLOCALOK) == 0) &&
|
|
||||||
#endif
|
|
||||||
(ifa_ifwithaddr((struct sockaddr *)sin) == 0))
|
|
||||||
return (EADDRNOTAVAIL);
|
return (EADDRNOTAVAIL);
|
||||||
}
|
}
|
||||||
laddr = sin->sin_addr;
|
laddr = sin->sin_addr;
|
||||||
|
@ -410,8 +410,7 @@ void inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp,
|
|||||||
#define INP_FAITH 0x00000200 /* accept FAITH'ed connections */
|
#define INP_FAITH 0x00000200 /* accept FAITH'ed connections */
|
||||||
#define INP_RECVTTL 0x00000400 /* receive incoming IP TTL */
|
#define INP_RECVTTL 0x00000400 /* receive incoming IP TTL */
|
||||||
#define INP_DONTFRAG 0x00000800 /* don't fragment packet */
|
#define INP_DONTFRAG 0x00000800 /* don't fragment packet */
|
||||||
#define INP_NONLOCALOK 0x00001000 /* Allow bind to spoof any address */
|
#define INP_BINDANY 0x00001000 /* allow bind to any address */
|
||||||
/* - requires options IP_NONLOCALBIND */
|
|
||||||
#define INP_INHASHLIST 0x00002000 /* in_pcbinshash() has been called */
|
#define INP_INHASHLIST 0x00002000 /* in_pcbinshash() has been called */
|
||||||
#define IN6P_IPV6_V6ONLY 0x00008000 /* restrict AF_INET6 socket for v6 */
|
#define IN6P_IPV6_V6ONLY 0x00008000 /* restrict AF_INET6 socket for v6 */
|
||||||
#define IN6P_PKTINFO 0x00010000 /* receive IP6 dst and I/F */
|
#define IN6P_PKTINFO 0x00010000 /* receive IP6 dst and I/F */
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include "opt_ipfw.h"
|
#include "opt_ipfw.h"
|
||||||
#include "opt_inet.h"
|
|
||||||
#include "opt_ipsec.h"
|
#include "opt_ipsec.h"
|
||||||
#include "opt_route.h"
|
#include "opt_route.h"
|
||||||
#include "opt_mac.h"
|
#include "opt_mac.h"
|
||||||
@ -103,12 +102,6 @@ SYSCTL_INT(_net_inet_ip, OID_AUTO, mbuf_frag_size, CTLFLAG_RW,
|
|||||||
&mbuf_frag_size, 0, "Fragment outgoing mbufs to this size");
|
&mbuf_frag_size, 0, "Fragment outgoing mbufs to this size");
|
||||||
#endif
|
#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
|
static void ip_mloopback
|
||||||
(struct ifnet *, struct mbuf *, struct sockaddr_in *, int);
|
(struct ifnet *, struct mbuf *, struct sockaddr_in *, int);
|
||||||
|
|
||||||
@ -931,14 +924,14 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(IP_NONLOCALBIND)
|
case IP_BINDANY:
|
||||||
case IP_NONLOCALOK:
|
if (sopt->sopt_td != NULL) {
|
||||||
if (! ip_nonlocalok) {
|
error = priv_check(sopt->sopt_td,
|
||||||
error = ENOPROTOOPT;
|
PRIV_NETINET_BINDANY);
|
||||||
break;
|
if (error)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
#endif
|
|
||||||
case IP_TOS:
|
case IP_TOS:
|
||||||
case IP_TTL:
|
case IP_TTL:
|
||||||
case IP_MINTTL:
|
case IP_MINTTL:
|
||||||
@ -1010,11 +1003,9 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
|
|||||||
case IP_DONTFRAG:
|
case IP_DONTFRAG:
|
||||||
OPTSET(INP_DONTFRAG);
|
OPTSET(INP_DONTFRAG);
|
||||||
break;
|
break;
|
||||||
#if defined(IP_NONLOCALBIND)
|
case IP_BINDANY:
|
||||||
case IP_NONLOCALOK:
|
OPTSET(INP_BINDANY);
|
||||||
OPTSET(INP_NONLOCALOK);
|
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#undef OPTSET
|
#undef OPTSET
|
||||||
|
@ -853,15 +853,16 @@ rip_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
|
|||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
|
inp = sotoinpcb(so);
|
||||||
|
KASSERT(inp != NULL, ("rip_bind: inp == NULL"));
|
||||||
|
|
||||||
if (TAILQ_EMPTY(&V_ifnet) ||
|
if (TAILQ_EMPTY(&V_ifnet) ||
|
||||||
(addr->sin_family != AF_INET && addr->sin_family != AF_IMPLINK) ||
|
(addr->sin_family != AF_INET && addr->sin_family != AF_IMPLINK) ||
|
||||||
(addr->sin_addr.s_addr &&
|
(addr->sin_addr.s_addr &&
|
||||||
ifa_ifwithaddr((struct sockaddr *)addr) == 0))
|
(inp->inp_flags & INP_BINDANY) == 0 &&
|
||||||
|
ifa_ifwithaddr((struct sockaddr *)addr) == NULL))
|
||||||
return (EADDRNOTAVAIL);
|
return (EADDRNOTAVAIL);
|
||||||
|
|
||||||
inp = sotoinpcb(so);
|
|
||||||
KASSERT(inp != NULL, ("rip_bind: inp == NULL"));
|
|
||||||
|
|
||||||
INP_INFO_WLOCK(&V_ripcbinfo);
|
INP_INFO_WLOCK(&V_ripcbinfo);
|
||||||
INP_WLOCK(inp);
|
INP_WLOCK(inp);
|
||||||
rip_delhash(inp);
|
rip_delhash(inp);
|
||||||
|
@ -477,6 +477,8 @@ struct route_in6 {
|
|||||||
* the source address.
|
* the source address.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define IPV6_BINDANY 64 /* bool: allow bind to any address */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following option is private; do not use it from user applications.
|
* The following option is private; do not use it from user applications.
|
||||||
* It is deliberately defined to the same value as IP_MSFILTER.
|
* It is deliberately defined to the same value as IP_MSFILTER.
|
||||||
|
@ -163,11 +163,13 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
|
|||||||
if (so->so_options & SO_REUSEADDR)
|
if (so->so_options & SO_REUSEADDR)
|
||||||
reuseport = SO_REUSEADDR|SO_REUSEPORT;
|
reuseport = SO_REUSEADDR|SO_REUSEPORT;
|
||||||
} else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
} else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||||
struct ifaddr *ia = NULL;
|
struct ifaddr *ia;
|
||||||
|
|
||||||
sin6->sin6_port = 0; /* yech... */
|
sin6->sin6_port = 0; /* yech... */
|
||||||
if ((ia = ifa_ifwithaddr((struct sockaddr *)sin6)) == 0)
|
if ((ia = ifa_ifwithaddr((struct sockaddr *)sin6)) == NULL &&
|
||||||
|
(inp->inp_flags & INP_BINDANY) == 0) {
|
||||||
return (EADDRNOTAVAIL);
|
return (EADDRNOTAVAIL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX: bind to an anycast address might accidentally
|
* XXX: bind to an anycast address might accidentally
|
||||||
|
@ -1405,6 +1405,14 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt)
|
|||||||
case IPV6_RECVTCLASS:
|
case IPV6_RECVTCLASS:
|
||||||
case IPV6_V6ONLY:
|
case IPV6_V6ONLY:
|
||||||
case IPV6_AUTOFLOWLABEL:
|
case IPV6_AUTOFLOWLABEL:
|
||||||
|
case IPV6_BINDANY:
|
||||||
|
if (optname == IPV6_BINDANY && td != NULL) {
|
||||||
|
error = priv_check(td,
|
||||||
|
PRIV_NETINET_BINDANY);
|
||||||
|
if (error)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (optlen != sizeof(int)) {
|
if (optlen != sizeof(int)) {
|
||||||
error = EINVAL;
|
error = EINVAL;
|
||||||
break;
|
break;
|
||||||
@ -1558,6 +1566,9 @@ do { \
|
|||||||
OPTSET(IN6P_AUTOFLOWLABEL);
|
OPTSET(IN6P_AUTOFLOWLABEL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IPV6_BINDANY:
|
||||||
|
OPTSET(INP_BINDANY);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1831,6 +1842,10 @@ do { \
|
|||||||
case IPV6_AUTOFLOWLABEL:
|
case IPV6_AUTOFLOWLABEL:
|
||||||
optval = OPTBIT(IN6P_AUTOFLOWLABEL);
|
optval = OPTBIT(IN6P_AUTOFLOWLABEL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IPV6_BINDANY:
|
||||||
|
optval = OPTBIT(INP_BINDANY);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (error)
|
if (error)
|
||||||
break;
|
break;
|
||||||
|
@ -374,6 +374,7 @@
|
|||||||
#define PRIV_NETINET_IPSEC 503 /* Administer IPSEC. */
|
#define PRIV_NETINET_IPSEC 503 /* Administer IPSEC. */
|
||||||
#define PRIV_NETINET_REUSEPORT 504 /* Allow [rapid] port/address reuse. */
|
#define PRIV_NETINET_REUSEPORT 504 /* Allow [rapid] port/address reuse. */
|
||||||
#define PRIV_NETINET_SETHDROPTS 505 /* Set certain IPv4/6 header options. */
|
#define PRIV_NETINET_SETHDROPTS 505 /* Set certain IPv4/6 header options. */
|
||||||
|
#define PRIV_NETINET_BINDANY 506 /* Allow bind to any address. */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IPX/SPX privileges.
|
* IPX/SPX privileges.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user