Merge branch 'bug17027-reject-private-all-interfaces-v2' into bug16069-bug17027
src/test/test_policy.c: Merged calls to policies_parse_exit_policy by adding additional arguments. fixup to remaining instance of ~EXIT_POLICY_IPV6_ENABLED. Compacting logic test now produces previous list length of 4, corrected this. src/config/torrc.sample.in: src/config/torrc.minimal.in-staging: Merged torrc modification dates in favour of latest.
This commit is contained in:
commit
a659a3fced
|
@ -0,0 +1,6 @@
|
|||
o Minor bug fixes (security, exit policies):
|
||||
- ExitPolicyRejectPrivate rejects more private addresses by default:
|
||||
* the relay's published IPv6 address (if any), and
|
||||
* any publicly routable IPv4 or IPv6 addresses on any local interfaces.
|
||||
Resolves ticket 17027. Patch by "teor".
|
||||
Patch on 42b8fb5a1523 (11 Nov 2007), released in 0.2.0.11-alpha.
|
|
@ -1590,8 +1590,11 @@ is non-zero):
|
|||
IPv4 and IPv6 addresses.
|
||||
|
||||
[[ExitPolicyRejectPrivate]] **ExitPolicyRejectPrivate** **0**|**1**::
|
||||
Reject all private (local) networks, along with your own public IP address,
|
||||
at the beginning of your exit policy. See above entry on ExitPolicy.
|
||||
Reject all private (local) networks, along with your own configured public
|
||||
IPv4 and IPv6 addresses, at the beginning of your exit policy. Also reject
|
||||
any public IPv4 and IPv6 addresses on any interface on the relay. (If
|
||||
IPv6Exit is not set, all IPv6 addresses will be rejected anyway.)
|
||||
See above entry on ExitPolicy.
|
||||
(Default: 1)
|
||||
|
||||
[[IPv6Exit]] **IPv6Exit** **0**|**1**::
|
||||
|
|
|
@ -1527,7 +1527,7 @@ get_interface_addresses_raw(int severity)
|
|||
}
|
||||
|
||||
/** Return true iff <b>a</b> is a multicast address. */
|
||||
static int
|
||||
STATIC int
|
||||
tor_addr_is_multicast(const tor_addr_t *a)
|
||||
{
|
||||
sa_family_t family = tor_addr_family(a);
|
||||
|
@ -1617,43 +1617,108 @@ get_interface_address6_via_udp_socket_hack(int severity,
|
|||
return r;
|
||||
}
|
||||
|
||||
/** Set *<b>addr</b> to the IP address (if any) of whatever interface
|
||||
* connects to the Internet. This address should only be used in checking
|
||||
* whether our address has changed. Return 0 on success, -1 on failure.
|
||||
/** Set *<b>addr</b> to an arbitrary IP address (if any) of an interface that
|
||||
* connects to the Internet. Prefer public IP addresses to internal IP
|
||||
* addresses. This address should only be used in checking whether our
|
||||
* address has changed, as it may be an internal IP address. Return 0 on
|
||||
* success, -1 on failure.
|
||||
* Prefer get_interface_address6_list for a list of all addresses on all
|
||||
* interfaces which connect to the Internet.
|
||||
*/
|
||||
MOCK_IMPL(int,
|
||||
get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr))
|
||||
{
|
||||
/* XXX really, this function should yield a smartlist of addresses. */
|
||||
smartlist_t *addrs;
|
||||
int rv = -1;
|
||||
tor_assert(addr);
|
||||
|
||||
/* Get a list of public or internal IPs in arbitrary order */
|
||||
addrs = get_interface_address6_list(severity, family, 1);
|
||||
|
||||
/* Find the first non-internal address, or the last internal address
|
||||
* Ideally, we want the default route, see #12377 for details */
|
||||
SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a) {
|
||||
tor_addr_copy(addr, a);
|
||||
rv = 0;
|
||||
|
||||
/* If we found a non-internal address, declare success. Otherwise,
|
||||
* keep looking. */
|
||||
if (!tor_addr_is_internal(a, 0))
|
||||
break;
|
||||
} SMARTLIST_FOREACH_END(a);
|
||||
|
||||
free_interface_address6_list(addrs);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** Free a smartlist of IP addresses returned by get_interface_address6_list.
|
||||
*/
|
||||
void
|
||||
free_interface_address6_list(smartlist_t *addrs)
|
||||
{
|
||||
SMARTLIST_FOREACH(addrs, tor_addr_t *, a, tor_free(a));
|
||||
smartlist_free(addrs);
|
||||
}
|
||||
|
||||
/** Return a smartlist of the IP addresses of type family from all interfaces
|
||||
* on the server. Excludes loopback and multicast addresses. Only includes
|
||||
* internal addresses if include_internal is true. (Note that a relay behind
|
||||
* NAT may use an internal address to connect to the Internet.)
|
||||
* An empty smartlist means that there are no addresses of the selected type
|
||||
* matching these criteria.
|
||||
* Returns NULL on failure.
|
||||
* Use free_interface_address6_list to free the returned list.
|
||||
*/
|
||||
MOCK_IMPL(smartlist_t *,get_interface_address6_list,(int severity,
|
||||
sa_family_t family,
|
||||
int include_internal))
|
||||
{
|
||||
smartlist_t *addrs;
|
||||
tor_addr_t addr;
|
||||
|
||||
/* Try to do this the smart way if possible. */
|
||||
if ((addrs = get_interface_addresses_raw(severity))) {
|
||||
int rv = -1;
|
||||
SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a) {
|
||||
if (family != AF_UNSPEC && family != tor_addr_family(a))
|
||||
SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a)
|
||||
{
|
||||
if (family != AF_UNSPEC && family != tor_addr_family(a)) {
|
||||
SMARTLIST_DEL_CURRENT(addrs, a);
|
||||
tor_free(a);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tor_addr_is_loopback(a) ||
|
||||
tor_addr_is_multicast(a))
|
||||
tor_addr_is_multicast(a)) {
|
||||
SMARTLIST_DEL_CURRENT(addrs, a);
|
||||
tor_free(a);
|
||||
continue;
|
||||
}
|
||||
|
||||
tor_addr_copy(addr, a);
|
||||
rv = 0;
|
||||
|
||||
/* If we found a non-internal address, declare success. Otherwise,
|
||||
* keep looking. */
|
||||
if (!tor_addr_is_internal(a, 0))
|
||||
break;
|
||||
if (!include_internal && tor_addr_is_internal(a, 0)) {
|
||||
SMARTLIST_DEL_CURRENT(addrs, a);
|
||||
tor_free(a);
|
||||
continue;
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(a);
|
||||
}
|
||||
|
||||
SMARTLIST_FOREACH(addrs, tor_addr_t *, a, tor_free(a));
|
||||
if (addrs && smartlist_len(addrs) > 0) {
|
||||
return addrs;
|
||||
}
|
||||
|
||||
/* if we removed all entries as unsuitable */
|
||||
if (addrs) {
|
||||
smartlist_free(addrs);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Okay, the smart way is out. */
|
||||
return get_interface_address6_via_udp_socket_hack(severity,family,addr);
|
||||
get_interface_address6_via_udp_socket_hack(severity,family,&addr);
|
||||
if (!include_internal && tor_addr_is_internal(&addr, 0)) {
|
||||
return smartlist_new();
|
||||
} else {
|
||||
addrs = smartlist_new();
|
||||
smartlist_add(addrs, tor_dup_addr(&addr));
|
||||
return addrs;
|
||||
}
|
||||
}
|
||||
|
||||
/* ======
|
||||
|
@ -1895,10 +1960,13 @@ tor_dup_ip(uint32_t addr)
|
|||
}
|
||||
|
||||
/**
|
||||
* Set *<b>addr</b> to the host-order IPv4 address (if any) of whatever
|
||||
* interface connects to the Internet. This address should only be used in
|
||||
* checking whether our address has changed. Return 0 on success, -1 on
|
||||
* failure.
|
||||
* Set *<b>addr</b> to a host-order IPv4 address (if any) of an
|
||||
* interface that connects to the Internet. Prefer public IP addresses to
|
||||
* internal IP addresses. This address should only be used in checking
|
||||
* whether our address has changed, as it may be an internal IPv4 address.
|
||||
* Return 0 on success, -1 on failure.
|
||||
* Prefer get_interface_address_list6 for a list of all IPv4 and IPv6
|
||||
* addresses on all interfaces which connect to the Internet.
|
||||
*/
|
||||
MOCK_IMPL(int,
|
||||
get_interface_address,(int severity, uint32_t *addr))
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "orconfig.h"
|
||||
#include "torint.h"
|
||||
#include "compat.h"
|
||||
#include "container.h"
|
||||
|
||||
#ifdef ADDRESS_PRIVATE
|
||||
|
||||
|
@ -43,7 +44,6 @@
|
|||
#endif
|
||||
|
||||
// TODO win32 specific includes
|
||||
#include "container.h"
|
||||
#endif // ADDRESS_PRIVATE
|
||||
|
||||
/** The number of bits from an address to consider while doing a masked
|
||||
|
@ -190,8 +190,13 @@ char *tor_dup_addr(const tor_addr_t *addr) ATTR_MALLOC;
|
|||
const char *fmt_addr_impl(const tor_addr_t *addr, int decorate);
|
||||
const char *fmt_addrport(const tor_addr_t *addr, uint16_t port);
|
||||
const char * fmt_addr32(uint32_t addr);
|
||||
|
||||
MOCK_DECL(int,get_interface_address6,(int severity, sa_family_t family,
|
||||
tor_addr_t *addr));
|
||||
void free_interface_address6_list(smartlist_t * addrs);
|
||||
MOCK_DECL(smartlist_t *,get_interface_address6_list,(int severity,
|
||||
sa_family_t family,
|
||||
int include_internal));
|
||||
|
||||
/** Flag to specify how to do a comparison between addresses. In an "exact"
|
||||
* comparison, addresses are equivalent only if they are in the same family
|
||||
|
@ -281,11 +286,32 @@ int addr_mask_get_bits(uint32_t mask);
|
|||
int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len);
|
||||
char *tor_dup_ip(uint32_t addr) ATTR_MALLOC;
|
||||
MOCK_DECL(int,get_interface_address,(int severity, uint32_t *addr));
|
||||
/** Free a smartlist of IP addresses returned by get_interface_address_list.
|
||||
*/
|
||||
static INLINE void
|
||||
free_interface_address_list(smartlist_t *addrs)
|
||||
{
|
||||
free_interface_address6_list(addrs);
|
||||
}
|
||||
/** Return a smartlist of the IPv4 addresses of all interfaces on the server.
|
||||
* Excludes loopback and multicast addresses. Only includes internal addresses
|
||||
* if include_internal is true. (Note that a relay behind NAT may use an
|
||||
* internal address to connect to the Internet.)
|
||||
* An empty smartlist means that there are no IPv4 addresses.
|
||||
* Returns NULL on failure.
|
||||
* Use free_interface_address_list to free the returned list.
|
||||
*/
|
||||
static INLINE smartlist_t *
|
||||
get_interface_address_list(int severity, int include_internal)
|
||||
{
|
||||
return get_interface_address6_list(severity, AF_INET, include_internal);
|
||||
}
|
||||
|
||||
tor_addr_port_t *tor_addr_port_new(const tor_addr_t *addr, uint16_t port);
|
||||
|
||||
#ifdef ADDRESS_PRIVATE
|
||||
STATIC smartlist_t *get_interface_addresses_raw(int severity);
|
||||
STATIC int tor_addr_is_multicast(const tor_addr_t *a);
|
||||
STATIC int get_interface_address6_via_udp_socket_hack(int severity,
|
||||
sa_family_t family,
|
||||
tor_addr_t *addr);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
## Configuration file for a typical Tor user
|
||||
## Last updated 11 September 2015 for Tor 0.2.7.3-alpha.
|
||||
## Last updated 15 September 2015 for Tor 0.2.7.3-alpha.
|
||||
## (may or may not work for much older or much newer versions of Tor.)
|
||||
##
|
||||
## Lines that begin with "## " try to explain what's going on. Lines
|
||||
|
@ -172,8 +172,10 @@
|
|||
## users will be told that those destinations are down.
|
||||
##
|
||||
## For security, by default Tor rejects connections to private (local)
|
||||
## networks, including to your public IP address. See the man page entry
|
||||
## for ExitPolicyRejectPrivate if you want to allow "exit enclaving".
|
||||
## networks, including to the configured public IPv4 and IPv6 addresses,
|
||||
## and any public IPv4 and IPv6 addresses on any interface on the relay.
|
||||
## See the man page entry for ExitPolicyRejectPrivate if you want to allow
|
||||
## "exit enclaving".
|
||||
##
|
||||
#ExitPolicy accept *:6660-6667,reject *:* # allow irc ports on IPv4 and IPv6 but no more
|
||||
#ExitPolicy accept *:119 # accept nntp ports on IPv4 and IPv6 as well as default exit policy
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
## Configuration file for a typical Tor user
|
||||
## Last updated 11 September 2015 for Tor 0.2.7.3-alpha.
|
||||
## Last updated 15 September 2015 for Tor 0.2.7.3-alpha.
|
||||
## (may or may not work for much older or much newer versions of Tor.)
|
||||
##
|
||||
## Lines that begin with "## " try to explain what's going on. Lines
|
||||
|
@ -172,8 +172,10 @@
|
|||
## users will be told that those destinations are down.
|
||||
##
|
||||
## For security, by default Tor rejects connections to private (local)
|
||||
## networks, including to your public IP address. See the man page entry
|
||||
## for ExitPolicyRejectPrivate if you want to allow "exit enclaving".
|
||||
## networks, including to the configured public IPv4 and IPv6 addresses,
|
||||
## and any public IPv4 and IPv6 addresses on any interface on the relay.
|
||||
## See the man page entry for ExitPolicyRejectPrivate if you want to allow
|
||||
## "exit enclaving".
|
||||
##
|
||||
#ExitPolicy accept *:6660-6667,reject *:* # allow irc ports on IPv4 and IPv6 but no more
|
||||
#ExitPolicy accept *:119 # accept nntp ports on IPv4 and IPv6 as well as default exit policy
|
||||
|
|
|
@ -67,6 +67,8 @@ static int policies_parse_exit_policy_internal(config_line_t *cfg,
|
|||
int ipv6_exit,
|
||||
int rejectprivate,
|
||||
uint32_t local_address,
|
||||
tor_addr_t *ipv6_local_address,
|
||||
int reject_interface_addresses,
|
||||
int add_default_policy);
|
||||
|
||||
/** Replace all "private" entries in *<b>policy</b> with their expanded
|
||||
|
@ -441,7 +443,7 @@ validate_addr_policies(const or_options_t *options, char **msg)
|
|||
smartlist_t *addr_policy=NULL;
|
||||
*msg = NULL;
|
||||
|
||||
if (policies_parse_exit_policy_from_options(options,0,&addr_policy)) {
|
||||
if (policies_parse_exit_policy_from_options(options,0,NULL,0,&addr_policy)) {
|
||||
REJECT("Error in ExitPolicy entry.");
|
||||
}
|
||||
|
||||
|
@ -982,12 +984,24 @@ exit_policy_remove_redundancies(smartlist_t *dest)
|
|||
"reject *:563,reject *:1214,reject *:4661-4666," \
|
||||
"reject *:6346-6429,reject *:6699,reject *:6881-6999,accept *:*"
|
||||
|
||||
/** Parse the exit policy <b>cfg</b> into the linked list *<b>dest</b>. If
|
||||
* cfg doesn't end in an absolute accept or reject and if
|
||||
/** Parse the exit policy <b>cfg</b> into the linked list *<b>dest</b>.
|
||||
*
|
||||
* If <b>ipv6_exit</b> is true, prepend "reject *6:*" to the policy.
|
||||
*
|
||||
* If <b>rejectprivate</b> is true:
|
||||
* - prepend "reject private:*" to the policy.
|
||||
* - if local_address is non-zero, treat it as a host-order IPv4 address,
|
||||
* and prepend an entry that rejects it as a destination.
|
||||
* - if ipv6_local_address is non-NULL, prepend an entry that rejects it as
|
||||
* a destination.
|
||||
* - if reject_interface_addresses is true, prepend entries that reject each
|
||||
* public IPv4 and IPv6 address of each interface on this machine.
|
||||
*
|
||||
* If cfg doesn't end in an absolute accept or reject and if
|
||||
* <b>add_default_policy</b> is true, add the default exit
|
||||
* policy afterwards. If <b>rejectprivate</b> is true, prepend
|
||||
* "reject private:*" to the policy. Return -1 if we can't parse cfg,
|
||||
* else return 0.
|
||||
* policy afterwards.
|
||||
*
|
||||
* Return -1 if we can't parse cfg, else return 0.
|
||||
*
|
||||
* This function is used to parse the exit policy from our torrc. For
|
||||
* the functions used to parse the exit policy from a router descriptor,
|
||||
|
@ -998,17 +1012,78 @@ policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest,
|
|||
int ipv6_exit,
|
||||
int rejectprivate,
|
||||
uint32_t local_address,
|
||||
tor_addr_t *ipv6_local_address,
|
||||
int reject_interface_addresses,
|
||||
int add_default_policy)
|
||||
{
|
||||
if (!ipv6_exit) {
|
||||
append_exit_policy_string(dest, "reject *6:*");
|
||||
}
|
||||
if (rejectprivate) {
|
||||
/* Reject IPv4 and IPv6 reserved private netblocks */
|
||||
append_exit_policy_string(dest, "reject private:*");
|
||||
/* Reject our local IPv4 address */
|
||||
if (local_address) {
|
||||
char buf[POLICY_BUF_LEN];
|
||||
tor_snprintf(buf, sizeof(buf), "reject %s:*", fmt_addr32(local_address));
|
||||
append_exit_policy_string(dest, buf);
|
||||
log_info(LD_CONFIG, "Adding a reject ExitPolicy '%s' for our published "
|
||||
"IPv4 address", buf);
|
||||
}
|
||||
/* Reject our local IPv6 address */
|
||||
if (ipv6_exit && ipv6_local_address != NULL) {
|
||||
if (tor_addr_is_v4(ipv6_local_address)) {
|
||||
log_warn(LD_CONFIG, "IPv4 address '%s' provided as our IPv6 local "
|
||||
"address", fmt_addr(ipv6_local_address));
|
||||
} else {
|
||||
char buf6[POLICY_BUF_LEN];
|
||||
tor_snprintf(buf6, sizeof(buf6), "reject %s:*",
|
||||
fmt_addr(ipv6_local_address));
|
||||
append_exit_policy_string(dest, buf6);
|
||||
log_info(LD_CONFIG, "Adding a reject ExitPolicy '%s' for our "
|
||||
"published IPv6 address", buf6);
|
||||
}
|
||||
}
|
||||
/* Reject local addresses from public netblocks on any interface,
|
||||
* but don't reject our published addresses twice */
|
||||
if (reject_interface_addresses) {
|
||||
smartlist_t *public_addresses = NULL;
|
||||
char bufif[POLICY_BUF_LEN];
|
||||
|
||||
/* Reject public IPv4 addresses on any interface,
|
||||
* but don't reject our published IPv4 address twice */
|
||||
public_addresses = get_interface_address6_list(LOG_INFO, AF_INET, 0);
|
||||
SMARTLIST_FOREACH_BEGIN(public_addresses, tor_addr_t *, a) {
|
||||
if (!tor_addr_eq_ipv4h(a, local_address)) {
|
||||
tor_snprintf(bufif, sizeof(bufif), "reject %s:*",
|
||||
fmt_addr(a));
|
||||
append_exit_policy_string(dest, bufif);
|
||||
log_info(LD_CONFIG, "Adding a reject ExitPolicy '%s' for a local "
|
||||
"interface's public IPv4 address", bufif);
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(a);
|
||||
free_interface_address6_list(public_addresses);
|
||||
|
||||
if (ipv6_exit) {
|
||||
/* Reject public IPv6 addresses on any interface,
|
||||
* but don't reject our published IPv6 address (if any) twice */
|
||||
public_addresses = get_interface_address6_list(LOG_INFO, AF_INET6, 0);
|
||||
SMARTLIST_FOREACH_BEGIN(public_addresses, tor_addr_t *, a) {
|
||||
/* if we don't have an IPv6 local address, we won't have rejected
|
||||
* it above. This could happen if a future release does IPv6
|
||||
* autodiscovery, and we are waiting to discover our external IPv6
|
||||
* address */
|
||||
if (ipv6_local_address == NULL
|
||||
|| !tor_addr_eq(ipv6_local_address, a)) {
|
||||
tor_snprintf(bufif, sizeof(bufif), "reject6 %s:*",
|
||||
fmt_addr(a));
|
||||
append_exit_policy_string(dest, bufif);
|
||||
log_info(LD_CONFIG, "Adding a reject ExitPolicy '%s' for a local "
|
||||
"interface's public IPv6 address", bufif);
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(a);
|
||||
free_interface_address6_list(public_addresses);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parse_addr_policy(cfg, dest, -1))
|
||||
|
@ -1086,20 +1161,28 @@ policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest,
|
|||
|
||||
/** Parse exit policy in <b>cfg</b> into <b>dest</b> smartlist.
|
||||
*
|
||||
* Add entry that rejects all IPv6 destinations unless
|
||||
* Prepend an entry that rejects all IPv6 destinations unless
|
||||
* <b>EXIT_POLICY_IPV6_ENABLED</b> bit is set in <b>options</b> bitmask.
|
||||
*
|
||||
* If <b>EXIT_POLICY_REJECT_PRIVATE</b> bit is set in <b>options</b>,
|
||||
* do add entry that rejects all destinations in private subnetwork
|
||||
* Tor is running in.
|
||||
* If <b>EXIT_POLICY_REJECT_PRIVATE</b> bit is set in <b>options</b>:
|
||||
* - prepend an entry that rejects all destinations in all netblocks
|
||||
* reserved for private use.
|
||||
* - if local_address is non-zero, treat it as a host-order IPv4 address,
|
||||
* and prepend an entry that rejects it as a destination.
|
||||
* - if ipv6_local_address is non-NULL, prepend an entry that rejects it as
|
||||
* a destination.
|
||||
* - if reject_interface_addresses is true, prepend entries that reject each
|
||||
* public IPv4 and IPv6 address of each interface on this machine.
|
||||
*
|
||||
* Respectively, if <b>EXIT_POLICY_ADD_DEFAULT</b> bit is set, add
|
||||
* If <b>EXIT_POLICY_ADD_DEFAULT</b> bit is set in <b>options</b>, append
|
||||
* default exit policy entries to <b>result</b> smartlist.
|
||||
*/
|
||||
int
|
||||
policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
|
||||
exit_policy_parser_cfg_t options,
|
||||
uint32_t local_address)
|
||||
uint32_t local_address,
|
||||
tor_addr_t *ipv6_local_address,
|
||||
int reject_interface_addresses)
|
||||
{
|
||||
int ipv6_enabled = (options & EXIT_POLICY_IPV6_ENABLED) ? 1 : 0;
|
||||
int reject_private = (options & EXIT_POLICY_REJECT_PRIVATE) ? 1 : 0;
|
||||
|
@ -1108,19 +1191,27 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
|
|||
return policies_parse_exit_policy_internal(cfg,dest,ipv6_enabled,
|
||||
reject_private,
|
||||
local_address,
|
||||
ipv6_local_address,
|
||||
reject_interface_addresses,
|
||||
add_default);
|
||||
}
|
||||
|
||||
/** Parse <b>ExitPolicy</b> member of <b>or_options</b> into <b>result</b>
|
||||
* smartlist.
|
||||
* If <b>or_options->IPv6Exit</b> is false, add an entry that
|
||||
* If <b>or_options->IPv6Exit</b> is false, prepend an entry that
|
||||
* rejects all IPv6 destinations.
|
||||
*
|
||||
* If <b>or_options->ExitPolicyRejectPrivate</b> is true, add entry that
|
||||
* rejects all destinations in the private subnetwork of machine Tor
|
||||
* instance is running in.
|
||||
* If <b>or_options->ExitPolicyRejectPrivate</b> is true:
|
||||
* - prepend an entry that rejects all destinations in all netblocks reserved
|
||||
* for private use.
|
||||
* - if local_address is non-zero, treat it as a host-order IPv4 address, and
|
||||
* prepend an entry that rejects it as a destination.
|
||||
* - if ipv6_local_address is non-NULL, prepend an entry that rejects it as a
|
||||
* destination.
|
||||
* - if reject_interface_addresses is true, prepend entries that reject each
|
||||
* public IPv4 and IPv6 address of each interface on this machine.
|
||||
*
|
||||
* If <b>or_options->BridgeRelay</b> is false, add entries of default
|
||||
* If <b>or_options->BridgeRelay</b> is false, append entries of default
|
||||
* Tor exit policy into <b>result</b> smartlist.
|
||||
*
|
||||
* If or_options->ExitRelay is false, then make our exit policy into
|
||||
|
@ -1129,6 +1220,8 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
|
|||
int
|
||||
policies_parse_exit_policy_from_options(const or_options_t *or_options,
|
||||
uint32_t local_address,
|
||||
tor_addr_t *ipv6_local_address,
|
||||
int reject_interface_addresses,
|
||||
smartlist_t **result)
|
||||
{
|
||||
exit_policy_parser_cfg_t parser_cfg = 0;
|
||||
|
@ -1152,7 +1245,9 @@ policies_parse_exit_policy_from_options(const or_options_t *or_options,
|
|||
}
|
||||
|
||||
return policies_parse_exit_policy(or_options->ExitPolicy,result,
|
||||
parser_cfg,local_address);
|
||||
parser_cfg,local_address,
|
||||
ipv6_local_address,
|
||||
reject_interface_addresses);
|
||||
}
|
||||
|
||||
/** Add "reject *:*" to the end of the policy in *<b>dest</b>, allocating
|
||||
|
|
|
@ -48,18 +48,16 @@ MOCK_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy,
|
|||
addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr,
|
||||
uint16_t port, const node_t *node);
|
||||
|
||||
/*
|
||||
int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
|
||||
int ipv6exit,
|
||||
int rejectprivate, uint32_t local_address,
|
||||
int add_default_policy);
|
||||
*/
|
||||
int policies_parse_exit_policy_from_options(const or_options_t *or_options,
|
||||
uint32_t local_address,
|
||||
tor_addr_t *ipv6_local_address,
|
||||
int reject_interface_addresses,
|
||||
smartlist_t **result);
|
||||
int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
|
||||
exit_policy_parser_cfg_t options,
|
||||
uint32_t local_address);
|
||||
uint32_t local_address,
|
||||
tor_addr_t *ipv6_local_address,
|
||||
int reject_interface_addresses);
|
||||
void policies_exit_policy_append_reject_star(smartlist_t **dest);
|
||||
void addr_policy_append_reject_addr(smartlist_t **dest,
|
||||
const tor_addr_t *addr);
|
||||
|
|
|
@ -1922,7 +1922,7 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e)
|
|||
/* DNS is screwed up; don't claim to be an exit. */
|
||||
policies_exit_policy_append_reject_star(&ri->exit_policy);
|
||||
} else {
|
||||
policies_parse_exit_policy_from_options(options,ri->addr,
|
||||
policies_parse_exit_policy_from_options(options,ri->addr,&ri->ipv6_addr,1,
|
||||
&ri->exit_policy);
|
||||
}
|
||||
ri->policy_is_reject_star =
|
||||
|
|
|
@ -74,35 +74,79 @@ sockaddr_in_from_string(const char *ip_str, struct sockaddr_in *out)
|
|||
}
|
||||
|
||||
/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
|
||||
* that points to 127.0.0.1. Otherwise, return 0.
|
||||
* that is an IPv4 or IPv6 localhost address. Otherwise, return 0.
|
||||
*/
|
||||
static int
|
||||
smartlist_contains_localhost_tor_addr(smartlist_t *smartlist)
|
||||
{
|
||||
int found_localhost = 0;
|
||||
|
||||
struct sockaddr_in *sockaddr_localhost;
|
||||
struct sockaddr_storage *sockaddr_to_check;
|
||||
|
||||
sockaddr_localhost = sockaddr_in_from_string("127.0.0.1",NULL);
|
||||
|
||||
sockaddr_to_check = tor_malloc(sizeof(struct sockaddr_in));
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
|
||||
tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check,
|
||||
sizeof(struct sockaddr_in));
|
||||
|
||||
if (sockaddr_in_are_equal((struct sockaddr_in *)sockaddr_to_check,
|
||||
sockaddr_localhost)) {
|
||||
found_localhost = 1;
|
||||
break;
|
||||
if (tor_addr_is_loopback(tor_addr)) {
|
||||
return 1;
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(tor_addr);
|
||||
|
||||
tor_free(sockaddr_localhost);
|
||||
tor_free(sockaddr_to_check);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return found_localhost;
|
||||
/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
|
||||
* that is an IPv4 or IPv6 multicast address. Otherwise, return 0.
|
||||
*/
|
||||
static int
|
||||
smartlist_contains_multicast_tor_addr(smartlist_t *smartlist)
|
||||
{
|
||||
SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
|
||||
if (tor_addr_is_multicast(tor_addr)) {
|
||||
return 1;
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(tor_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
|
||||
* that is an IPv4 or IPv6 internal address. Otherwise, return 0.
|
||||
*/
|
||||
static int
|
||||
smartlist_contains_internal_tor_addr(smartlist_t *smartlist)
|
||||
{
|
||||
SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
|
||||
if (tor_addr_is_internal(tor_addr, 0)) {
|
||||
return 1;
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(tor_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
|
||||
* that is an IPv4 address. Otherwise, return 0.
|
||||
*/
|
||||
static int
|
||||
smartlist_contains_ipv4_tor_addr(smartlist_t *smartlist)
|
||||
{
|
||||
SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
|
||||
if (tor_addr_is_v4(tor_addr)) {
|
||||
return 1;
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(tor_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
|
||||
* that is an IPv6 address. Otherwise, return 0.
|
||||
*/
|
||||
static int
|
||||
smartlist_contains_ipv6_tor_addr(smartlist_t *smartlist)
|
||||
{
|
||||
SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
|
||||
/* Since there's no tor_addr_is_v6, assume all non-v4s are v6 */
|
||||
if (!tor_addr_is_v4(tor_addr)) {
|
||||
return 1;
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(tor_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_IFADDRS_TO_SMARTLIST
|
||||
|
@ -634,12 +678,168 @@ test_address_udp_socket_trick_blackbox(void *arg)
|
|||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
test_address_get_if_addrs_list_internal(void *arg)
|
||||
{
|
||||
smartlist_t *results = NULL;
|
||||
|
||||
(void)arg;
|
||||
|
||||
results = get_interface_address_list(LOG_ERR, 1);
|
||||
|
||||
tt_assert(results != NULL);
|
||||
/* Assume every system has at least 1 non-local non-multicast IPv4
|
||||
* interface, even if it is an internal one */
|
||||
tt_int_op(smartlist_len(results),>=,1);
|
||||
|
||||
tt_assert(!smartlist_contains_localhost_tor_addr(results));
|
||||
tt_assert(!smartlist_contains_multicast_tor_addr(results));
|
||||
/* The list may or may not contain internal addresses */
|
||||
|
||||
tt_assert(smartlist_contains_ipv4_tor_addr(results));
|
||||
tt_assert(!smartlist_contains_ipv6_tor_addr(results));
|
||||
|
||||
done:
|
||||
free_interface_address_list(results);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
test_address_get_if_addrs_list_no_internal(void *arg)
|
||||
{
|
||||
smartlist_t *results = NULL;
|
||||
|
||||
(void)arg;
|
||||
|
||||
results = get_interface_address_list(LOG_ERR, 0);
|
||||
|
||||
tt_assert(results != NULL);
|
||||
/* Work even on systems with only internal IPv4 addresses */
|
||||
tt_int_op(smartlist_len(results),>=,0);
|
||||
|
||||
tt_assert(!smartlist_contains_localhost_tor_addr(results));
|
||||
tt_assert(!smartlist_contains_multicast_tor_addr(results));
|
||||
tt_assert(!smartlist_contains_internal_tor_addr(results));
|
||||
|
||||
/* The list may or may not contain IPv4 addresses */
|
||||
tt_assert(!smartlist_contains_ipv6_tor_addr(results));
|
||||
|
||||
done:
|
||||
free_interface_address_list(results);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
test_address_get_if_addrs6_list_internal(void *arg)
|
||||
{
|
||||
smartlist_t *results = NULL;
|
||||
|
||||
(void)arg;
|
||||
|
||||
results = get_interface_address6_list(LOG_ERR, AF_INET6, 1);
|
||||
|
||||
tt_assert(results != NULL);
|
||||
/* Work even on systems without IPv6 interfaces */
|
||||
tt_int_op(smartlist_len(results),>=,0);
|
||||
|
||||
tt_assert(!smartlist_contains_localhost_tor_addr(results));
|
||||
tt_assert(!smartlist_contains_multicast_tor_addr(results));
|
||||
/* The list may or may not contain internal addresses */
|
||||
|
||||
tt_assert(!smartlist_contains_ipv4_tor_addr(results));
|
||||
/* The list may or may not contain IPv6 addresses */
|
||||
|
||||
done:
|
||||
free_interface_address6_list(results);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
test_address_get_if_addrs6_list_no_internal(void *arg)
|
||||
{
|
||||
smartlist_t *results = NULL;
|
||||
|
||||
(void)arg;
|
||||
|
||||
results = get_interface_address6_list(LOG_ERR, AF_INET6, 0);
|
||||
|
||||
tt_assert(results != NULL);
|
||||
/* Work even on systems without IPv6 interfaces */
|
||||
tt_int_op(smartlist_len(results),>=,0);
|
||||
|
||||
tt_assert(!smartlist_contains_localhost_tor_addr(results));
|
||||
tt_assert(!smartlist_contains_multicast_tor_addr(results));
|
||||
tt_assert(!smartlist_contains_internal_tor_addr(results));
|
||||
|
||||
tt_assert(!smartlist_contains_ipv4_tor_addr(results));
|
||||
/* The list may or may not contain IPv6 addresses */
|
||||
|
||||
done:
|
||||
free_interface_address6_list(results);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
test_address_get_if_addrs(void *arg)
|
||||
{
|
||||
int rv;
|
||||
uint32_t addr_h = 0;
|
||||
tor_addr_t tor_addr;
|
||||
|
||||
(void)arg;
|
||||
|
||||
rv = get_interface_address(LOG_ERR, &addr_h);
|
||||
|
||||
/* Assume every system has at least 1 non-local non-multicast IPv4
|
||||
* interface, even if it is an internal one */
|
||||
tt_assert(rv == 0);
|
||||
tor_addr_from_ipv4h(&tor_addr, addr_h);
|
||||
|
||||
tt_assert(!tor_addr_is_loopback(&tor_addr));
|
||||
tt_assert(!tor_addr_is_multicast(&tor_addr));
|
||||
/* The address may or may not be an internal address */
|
||||
|
||||
tt_assert(tor_addr_is_v4(&tor_addr));
|
||||
|
||||
done:
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
test_address_get_if_addrs6(void *arg)
|
||||
{
|
||||
int rv;
|
||||
tor_addr_t tor_addr;
|
||||
|
||||
(void)arg;
|
||||
|
||||
rv = get_interface_address6(LOG_ERR, AF_INET6, &tor_addr);
|
||||
|
||||
/* Work even on systems without IPv6 interfaces */
|
||||
if (rv == 0) {
|
||||
tt_assert(!tor_addr_is_loopback(&tor_addr));
|
||||
tt_assert(!tor_addr_is_multicast(&tor_addr));
|
||||
/* The address may or may not be an internal address */
|
||||
|
||||
tt_assert(!tor_addr_is_v4(&tor_addr));
|
||||
}
|
||||
|
||||
done:
|
||||
return;
|
||||
}
|
||||
|
||||
#define ADDRESS_TEST(name, flags) \
|
||||
{ #name, test_address_ ## name, flags, NULL, NULL }
|
||||
|
||||
struct testcase_t address_tests[] = {
|
||||
ADDRESS_TEST(udp_socket_trick_whitebox, TT_FORK),
|
||||
ADDRESS_TEST(udp_socket_trick_blackbox, TT_FORK),
|
||||
ADDRESS_TEST(get_if_addrs_list_internal, 0),
|
||||
ADDRESS_TEST(get_if_addrs_list_no_internal, 0),
|
||||
ADDRESS_TEST(get_if_addrs6_list_internal, 0),
|
||||
ADDRESS_TEST(get_if_addrs6_list_no_internal, 0),
|
||||
ADDRESS_TEST(get_if_addrs, 0),
|
||||
ADDRESS_TEST(get_if_addrs6, 0),
|
||||
#ifdef HAVE_IFADDRS_TO_SMARTLIST
|
||||
ADDRESS_TEST(get_if_addrs_ifaddrs, TT_FORK),
|
||||
ADDRESS_TEST(ifaddrs_to_smartlist, 0),
|
||||
|
|
|
@ -49,7 +49,7 @@ test_policy_summary_helper(const char *policy_str,
|
|||
|
||||
r = policies_parse_exit_policy(&line, &policy,
|
||||
EXIT_POLICY_IPV6_ENABLED |
|
||||
EXIT_POLICY_ADD_DEFAULT ,0);
|
||||
EXIT_POLICY_ADD_DEFAULT, 0, NULL, 0);
|
||||
tt_int_op(r,OP_EQ, 0);
|
||||
|
||||
summary = policy_summarize(policy, AF_INET);
|
||||
|
@ -78,7 +78,7 @@ test_policies_general(void *arg)
|
|||
smartlist_t *policy = NULL, *policy2 = NULL, *policy3 = NULL,
|
||||
*policy4 = NULL, *policy5 = NULL, *policy6 = NULL,
|
||||
*policy7 = NULL, *policy8 = NULL, *policy9 = NULL,
|
||||
*policy10 = NULL, *policy11 = NULL;
|
||||
*policy10 = NULL, *policy11 = NULL, *policy12 = NULL;
|
||||
addr_policy_t *p;
|
||||
tor_addr_t tar;
|
||||
config_line_t line;
|
||||
|
@ -115,10 +115,20 @@ test_policies_general(void *arg)
|
|||
tt_int_op(0, OP_EQ, policies_parse_exit_policy(NULL, &policy2,
|
||||
EXIT_POLICY_IPV6_ENABLED |
|
||||
EXIT_POLICY_REJECT_PRIVATE |
|
||||
EXIT_POLICY_ADD_DEFAULT, 0));
|
||||
EXIT_POLICY_ADD_DEFAULT, 0,
|
||||
NULL, 0));
|
||||
|
||||
tt_assert(policy2);
|
||||
|
||||
tor_addr_parse(&tar, "[2000::1234]");
|
||||
tt_int_op(0, OP_EQ, policies_parse_exit_policy(NULL, &policy12,
|
||||
EXIT_POLICY_IPV6_ENABLED |
|
||||
EXIT_POLICY_REJECT_PRIVATE |
|
||||
EXIT_POLICY_ADD_DEFAULT,
|
||||
0x0306090cu, &tar, 1));
|
||||
|
||||
tt_assert(policy12);
|
||||
|
||||
policy3 = smartlist_new();
|
||||
p = router_parse_addr_policy_item_from_string("reject *:*", -1,
|
||||
&malformed_list);
|
||||
|
@ -196,13 +206,15 @@ test_policies_general(void *arg)
|
|||
tt_int_op(0, OP_EQ, policies_parse_exit_policy(NULL, &policy8,
|
||||
EXIT_POLICY_IPV6_ENABLED |
|
||||
EXIT_POLICY_REJECT_PRIVATE |
|
||||
EXIT_POLICY_ADD_DEFAULT, 0));
|
||||
EXIT_POLICY_ADD_DEFAULT, 0,
|
||||
NULL, 0));
|
||||
|
||||
tt_assert(policy8);
|
||||
|
||||
tt_int_op(0, OP_EQ, policies_parse_exit_policy(NULL, &policy9,
|
||||
EXIT_POLICY_REJECT_PRIVATE |
|
||||
EXIT_POLICY_ADD_DEFAULT, 0));
|
||||
EXIT_POLICY_ADD_DEFAULT, 0,
|
||||
NULL, 0));
|
||||
|
||||
tt_assert(policy9);
|
||||
|
||||
|
@ -255,13 +267,14 @@ test_policies_general(void *arg)
|
|||
line.value = (char*)"accept *:80,reject private:*,reject *:*";
|
||||
line.next = NULL;
|
||||
tt_int_op(0, OP_EQ, policies_parse_exit_policy(&line,&policy,
|
||||
~EXIT_POLICY_IPV6_ENABLED |
|
||||
EXIT_POLICY_ADD_DEFAULT,0));
|
||||
EXIT_POLICY_IPV6_ENABLED |
|
||||
EXIT_POLICY_ADD_DEFAULT, 0,
|
||||
NULL, 0));
|
||||
tt_assert(policy);
|
||||
|
||||
//test_streq(policy->string, "accept *:80");
|
||||
//test_streq(policy->next->string, "reject *:*");
|
||||
tt_int_op(smartlist_len(policy),OP_EQ, 9);
|
||||
tt_int_op(smartlist_len(policy),OP_EQ, 4);
|
||||
|
||||
/* test policy summaries */
|
||||
/* check if we properly ignore private IP addresses */
|
||||
|
@ -467,6 +480,7 @@ test_policies_general(void *arg)
|
|||
addr_policy_list_free(policy9);
|
||||
addr_policy_list_free(policy10);
|
||||
addr_policy_list_free(policy11);
|
||||
addr_policy_list_free(policy12);
|
||||
tor_free(policy_str);
|
||||
if (sm) {
|
||||
SMARTLIST_FOREACH(sm, char *, s, tor_free(s));
|
||||
|
|
Loading…
Reference in New Issue