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:
teor (Tim Wilson-Brown) 2015-09-16 09:09:54 +10:00
commit a659a3fced
11 changed files with 500 additions and 86 deletions

View File

@ -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.

View File

@ -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**::

View File

@ -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))

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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 =

View File

@ -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),

View File

@ -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));