mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Merge remote-tracking branch 'teor/bug16069-bug17027'
This commit is contained in:
commit
b257e34583
20
changes/bug16069-exit-policy-rule6
Normal file
20
changes/bug16069-exit-policy-rule6
Normal file
@ -0,0 +1,20 @@
|
||||
o Minor bug fixes (torrc exit policies):
|
||||
- accept6/reject6 * lines only produce IPv6 wildcard addresses,
|
||||
previously they would produce both IPv4 and IPv6 wildcard addresses.
|
||||
- When parsing torrc ExitPolicies, we now warn if:
|
||||
* an IPv4 address is used on an accept6 or reject6 line. The line is
|
||||
ignored, but the rest of the policy items in the list are used.
|
||||
(accept/reject continue to allow both IPv4 and IPv6 addresses in
|
||||
torrcs.)
|
||||
* a "private" address alias is used on an accept6 or reject6 line.
|
||||
The line filters both IPv4 and IPv6 private addresses, disregarding
|
||||
the 6 in accept6/reject6.
|
||||
* any ExitPolicy lines occur after accept/reject *:* or variants.
|
||||
These are redundant, and were always ignored.
|
||||
- When parsing torrc ExitPolicies, we now issue an info-level message:
|
||||
* when expanding an accept/reject * line to include both IPv4 and IPv6
|
||||
wildcard addresses.
|
||||
- In each instance, usage advice is provided to avoid the message.
|
||||
Resolves ticket 16069. Patch by "teor".
|
||||
Patch on 2eb7eafc9d78 and a96c0affcb4c (25 Oct 2012),
|
||||
released in 0.2.4.7-alpha.
|
6
changes/bug17027-reject-private-all-interfaces
Normal file
6
changes/bug17027-reject-private-all-interfaces
Normal 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.
|
@ -1537,12 +1537,26 @@ is non-zero):
|
||||
"\*". +
|
||||
+
|
||||
For example, "accept 18.7.22.69:\*,reject 18.0.0.0/8:\*,accept \*:\*" would
|
||||
reject any traffic destined for MIT except for web.mit.edu, and accept
|
||||
anything else. +
|
||||
reject any IPv4 traffic destined for MIT except for web.mit.edu, and accept
|
||||
any other IPv4 or IPv6 traffic. +
|
||||
+
|
||||
To specify all internal and link-local networks (including 0.0.0.0/8,
|
||||
169.254.0.0/16, 127.0.0.0/8, 192.168.0.0/16, 10.0.0.0/8, and
|
||||
172.16.0.0/12), you can use the "private" alias instead of an address.
|
||||
Tor also allows IPv6 exit policy entries. For instance, "reject6 [FC00::]/7:*"
|
||||
rejects all destinations that share 7 most significant bit prefix with
|
||||
address FC00::. Respectively, "accept6 [C000::]/3:*" accepts all destinations
|
||||
that share 3 most significant bit prefix with address C000::. +
|
||||
+
|
||||
accept6 and reject6 only produce IPv6 exit policy entries. Using an IPv4
|
||||
address with accept6 or reject6 is ignored and generates a warning.
|
||||
accept/reject allows either IPv4 or IPv6 addresses. Use *4 as an IPv4
|
||||
wildcard address, and *6 as an IPv6 wildcard address. accept/reject *
|
||||
expands to matching IPv4 and IPv6 wildcard address rules. +
|
||||
+
|
||||
To specify all IPv4 and IPv6 internal and link-local networks (including
|
||||
0.0.0.0/8, 169.254.0.0/16, 127.0.0.0/8, 192.168.0.0/16, 10.0.0.0/8,
|
||||
172.16.0.0/12, [::]/8, [FC00::]/7, [FE80::]/10, [FEC0::]/10, [FF00::]/8,
|
||||
and [::]/127), you can use the "private" alias instead of an address.
|
||||
("private" always produces rules for IPv4 and IPv6 addresses, even when
|
||||
used with accept6/reject6.)
|
||||
These addresses are rejected by default (at the beginning of your exit
|
||||
policy), along with your public IP address, unless you set the
|
||||
ExitPolicyRejectPrivate config option to 0. For example, once you've done
|
||||
@ -1551,11 +1565,6 @@ is non-zero):
|
||||
may also allow connections to your own computer that are addressed to its
|
||||
public (external) IP address. See RFC 1918 and RFC 3330 for more details
|
||||
about internal and reserved IP address space. +
|
||||
+
|
||||
Tor also allow IPv6 exit policy entries. For instance, "reject6 [FC00::]/7:*"
|
||||
rejects all destinations that share 7 most significant bit prefix with
|
||||
address FC00::. Respectively, "accept6 [C000::]/3:*" accepts all destinations
|
||||
that share 3 most significant bit prefix with address C000::. +
|
||||
+
|
||||
This directive can be specified multiple times so you don't have to put it
|
||||
all on one line. +
|
||||
@ -1577,9 +1586,15 @@ is non-zero):
|
||||
reject *:6881-6999
|
||||
accept *:*
|
||||
|
||||
Since the default exit policy uses accept/reject *, it applies to both
|
||||
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**::
|
||||
|
@ -620,13 +620,20 @@ tor_addr_to_PTR_name(char *out, size_t outlen,
|
||||
* yield an IPv4 wildcard.
|
||||
*
|
||||
* If 'flags & TAPMP_EXTENDED_STAR' is true, then the wildcard address '*'
|
||||
* yields an AF_UNSPEC wildcard address, and the following change is made
|
||||
* yields an AF_UNSPEC wildcard address, which expands to corresponding
|
||||
* wildcard IPv4 and IPv6 rules, and the following change is made
|
||||
* in the grammar above:
|
||||
* Address ::= IPv4Address / "[" IPv6Address "]" / "*" / "*4" / "*6"
|
||||
* with the new "*4" and "*6" productions creating a wildcard to match
|
||||
* IPv4 or IPv6 addresses.
|
||||
*
|
||||
*/
|
||||
* If 'flags & TAPMP_EXTENDED_STAR' and 'flags & TAPMP_STAR_IPV4_ONLY' are
|
||||
* both true, then the wildcard address '*' yields an IPv4 wildcard.
|
||||
*
|
||||
* If 'flags & TAPMP_EXTENDED_STAR' and 'flags & TAPMP_STAR_IPV6_ONLY' are
|
||||
* both true, then the wildcard address '*' yields an IPv6 wildcard.
|
||||
*
|
||||
* TAPMP_STAR_IPV4_ONLY and TAPMP_STAR_IPV6_ONLY are mutually exclusive. */
|
||||
int
|
||||
tor_addr_parse_mask_ports(const char *s,
|
||||
unsigned flags,
|
||||
@ -643,6 +650,10 @@ tor_addr_parse_mask_ports(const char *s,
|
||||
|
||||
tor_assert(s);
|
||||
tor_assert(addr_out);
|
||||
/* We can either only want an IPv4 address or only want an IPv6 address,
|
||||
* but we can't only want IPv4 & IPv6 at the same time. */
|
||||
tor_assert(!((flags & TAPMP_STAR_IPV4_ONLY)
|
||||
&& (flags & TAPMP_STAR_IPV6_ONLY)));
|
||||
|
||||
/** Longest possible length for an address, mask, and port-range combination.
|
||||
* Includes IP, [], /mask, :, ports */
|
||||
@ -688,8 +699,21 @@ tor_addr_parse_mask_ports(const char *s,
|
||||
|
||||
if (!strcmp(address, "*")) {
|
||||
if (flags & TAPMP_EXTENDED_STAR) {
|
||||
family = AF_UNSPEC;
|
||||
tor_addr_make_unspec(addr_out);
|
||||
if (flags & TAPMP_STAR_IPV4_ONLY) {
|
||||
family = AF_INET;
|
||||
tor_addr_from_ipv4h(addr_out, 0);
|
||||
} else if (flags & TAPMP_STAR_IPV6_ONLY) {
|
||||
static char nil_bytes[16] = { [0]=0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
|
||||
family = AF_INET6;
|
||||
tor_addr_from_ipv6_bytes(addr_out, nil_bytes);
|
||||
} else {
|
||||
family = AF_UNSPEC;
|
||||
tor_addr_make_unspec(addr_out);
|
||||
log_info(LD_GENERAL,
|
||||
"'%s' expands into rules which apply to all IPv4 and IPv6 "
|
||||
"addresses. (Use accept/reject *4:* for IPv4 or "
|
||||
"accept[6]/reject[6] *6:* for IPv6.)", s);
|
||||
}
|
||||
} else {
|
||||
family = AF_INET;
|
||||
tor_addr_from_ipv4h(addr_out, 0);
|
||||
@ -1503,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);
|
||||
@ -1593,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;
|
||||
}
|
||||
}
|
||||
|
||||
/* ======
|
||||
@ -1871,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
|
||||
@ -227,7 +232,19 @@ int tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
|
||||
|
||||
int tor_addr_port_lookup(const char *s, tor_addr_t *addr_out,
|
||||
uint16_t *port_out);
|
||||
|
||||
/* Does the address * yield an AF_UNSPEC wildcard address (1),
|
||||
* which expands to corresponding wildcard IPv4 and IPv6 rules, and do we
|
||||
* allow *4 and *6 for IPv4 and IPv6 wildcards, respectively;
|
||||
* or does the address * yield IPv4 wildcard address (0). */
|
||||
#define TAPMP_EXTENDED_STAR 1
|
||||
/* Does the address * yield an IPv4 wildcard address rule (1);
|
||||
* or does it yield wildcard IPv4 and IPv6 rules (0) */
|
||||
#define TAPMP_STAR_IPV4_ONLY (1 << 1)
|
||||
/* Does the address * yield an IPv6 wildcard address rule (1);
|
||||
* or does it yield wildcard IPv4 and IPv6 rules (0) */
|
||||
#define TAPMP_STAR_IPV6_ONLY (1 << 2)
|
||||
/* TAPMP_STAR_IPV4_ONLY and TAPMP_STAR_IPV6_ONLY are mutually exclusive. */
|
||||
int tor_addr_parse_mask_ports(const char *s, unsigned flags,
|
||||
tor_addr_t *addr_out, maskbits_t *mask_out,
|
||||
uint16_t *port_min_out, uint16_t *port_max_out);
|
||||
@ -269,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 2 September 2014 for Tor 0.2.6.1-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
|
||||
@ -24,6 +24,7 @@
|
||||
## can access your SocksPort may be able to learn about the connections
|
||||
## you make.
|
||||
#SocksPolicy accept 192.168.0.0/16
|
||||
#SocksPolicy accept6 FC00::/7
|
||||
#SocksPolicy reject *
|
||||
|
||||
## Logs go to stdout at level "notice" unless redirected by something
|
||||
@ -171,11 +172,15 @@
|
||||
## 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 but no more
|
||||
#ExitPolicy accept *:119 # accept nntp as well as default exit policy
|
||||
#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
|
||||
#ExitPolicy accept *4:119 # accept nntp ports on IPv4 only as well as default exit policy
|
||||
#ExitPolicy accept6 *6:119 # accept nntp ports on IPv6 only as well as default exit policy
|
||||
#ExitPolicy reject *:* # no exits allowed
|
||||
|
||||
## Bridge relays (or "bridges") are Tor relays that aren't listed in the
|
||||
|
@ -1,5 +1,5 @@
|
||||
## Configuration file for a typical Tor user
|
||||
## Last updated 2 September 2014 for Tor 0.2.6.1-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
|
||||
@ -24,6 +24,7 @@
|
||||
## can access your SocksPort may be able to learn about the connections
|
||||
## you make.
|
||||
#SocksPolicy accept 192.168.0.0/16
|
||||
#SocksPolicy accept6 FC00::/7
|
||||
#SocksPolicy reject *
|
||||
|
||||
## Logs go to stdout at level "notice" unless redirected by something
|
||||
@ -171,11 +172,15 @@
|
||||
## 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 but no more
|
||||
#ExitPolicy accept *:119 # accept nntp as well as default exit policy
|
||||
#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
|
||||
#ExitPolicy accept *4:119 # accept nntp ports on IPv4 only as well as default exit policy
|
||||
#ExitPolicy accept6 *6:119 # accept nntp ports on IPv6 only as well as default exit policy
|
||||
#ExitPolicy reject *:* # no exits allowed
|
||||
|
||||
## Bridge relays (or "bridges") are Tor relays that aren't listed in the
|
||||
|
@ -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
|
||||
@ -152,7 +154,7 @@ policy_expand_unspec(smartlist_t **policy)
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a linked list of config lines containing "allow" and "deny"
|
||||
* Given a linked list of config lines containing "accept[6]" and "reject[6]"
|
||||
* tokens, parse them and append the result to <b>dest</b>. Return -1
|
||||
* if any tokens are malformed (and don't append any), else return 0.
|
||||
*
|
||||
@ -167,6 +169,7 @@ parse_addr_policy(config_line_t *cfg, smartlist_t **dest,
|
||||
smartlist_t *result;
|
||||
smartlist_t *entries;
|
||||
addr_policy_t *item;
|
||||
int malformed_list;
|
||||
int r = 0;
|
||||
|
||||
if (!cfg)
|
||||
@ -179,12 +182,22 @@ parse_addr_policy(config_line_t *cfg, smartlist_t **dest,
|
||||
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
|
||||
SMARTLIST_FOREACH_BEGIN(entries, const char *, ent) {
|
||||
log_debug(LD_CONFIG,"Adding new entry '%s'",ent);
|
||||
item = router_parse_addr_policy_item_from_string(ent, assume_action);
|
||||
malformed_list = 0;
|
||||
item = router_parse_addr_policy_item_from_string(ent, assume_action,
|
||||
&malformed_list);
|
||||
if (item) {
|
||||
smartlist_add(result, item);
|
||||
} else {
|
||||
log_warn(LD_CONFIG,"Malformed policy '%s'.", ent);
|
||||
} else if (malformed_list) {
|
||||
/* the error is so severe the entire list should be discarded */
|
||||
log_warn(LD_CONFIG, "Malformed policy '%s'. Discarding entire policy "
|
||||
"list.", ent);
|
||||
r = -1;
|
||||
} else {
|
||||
/* the error is minor: don't add the item, but keep processing the
|
||||
* rest of the policies in the list */
|
||||
log_debug(LD_CONFIG, "Ignored policy '%s' due to non-fatal error. "
|
||||
"The remainder of the policy list will be used.",
|
||||
ent);
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(ent);
|
||||
SMARTLIST_FOREACH(entries, char *, ent, tor_free(ent));
|
||||
@ -430,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.");
|
||||
}
|
||||
|
||||
@ -568,6 +581,8 @@ cmp_single_addr_policy(addr_policy_t *a, addr_policy_t *b)
|
||||
return r;
|
||||
if ((r=((int)a->is_private - (int)b->is_private)))
|
||||
return r;
|
||||
/* refcnt and is_canonical are irrelevant to equality,
|
||||
* they are hash table implementation details */
|
||||
if ((r=tor_addr_compare(&a->addr, &b->addr, CMP_EXACT)))
|
||||
return r;
|
||||
if ((r=((int)a->maskbits - (int)b->maskbits)))
|
||||
@ -969,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,
|
||||
@ -985,21 +1012,142 @@ 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))
|
||||
return -1;
|
||||
|
||||
/* Before we add the default policy and final rejects, check to see if
|
||||
* there are any lines after accept *:* or reject *:*. These lines have no
|
||||
* effect, and are most likely an error. */
|
||||
int found_final_effective_entry = 0;
|
||||
int first_redundant_entry = 0;
|
||||
for (int i = 0; i < smartlist_len(*dest); ++i) {
|
||||
sa_family_t family;
|
||||
addr_policy_t *p;
|
||||
int found_ipv4_wildcard = 0, found_ipv6_wildcard = 0;
|
||||
|
||||
p = smartlist_get(*dest, i);
|
||||
|
||||
/* Look for accept/reject *[4|6|]:* entires */
|
||||
if (p->prt_min <= 1 && p->prt_max == 65535 && p->maskbits == 0) {
|
||||
family = tor_addr_family(&p->addr);
|
||||
/* accept/reject *:* may have already been expanded into
|
||||
* accept/reject *4:*,accept/reject *6:*
|
||||
* But handle both forms.
|
||||
*/
|
||||
if (family == AF_INET || family == AF_UNSPEC) {
|
||||
found_ipv4_wildcard = 1;
|
||||
}
|
||||
if (family == AF_INET6 || family == AF_UNSPEC) {
|
||||
found_ipv6_wildcard = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* We also find accept *4:*,reject *6:* ; and
|
||||
* accept *4:*,<other policies>,accept *6:* ; and similar.
|
||||
* That's ok, because they make any subsequent entries redundant. */
|
||||
if (found_ipv4_wildcard && found_ipv6_wildcard) {
|
||||
found_final_effective_entry = 1;
|
||||
/* if we're not on the final entry in the list */
|
||||
if (i < smartlist_len(*dest) - 1) {
|
||||
first_redundant_entry = i + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Work out if there are redundant trailing entries in the policy list */
|
||||
if (found_final_effective_entry && first_redundant_entry > 0) {
|
||||
addr_policy_t *p;
|
||||
/* Longest possible policy is
|
||||
* "accept6 ffff:ffff:..255/128:10000-65535",
|
||||
* which contains a max-length IPv6 address, plus 24 characters. */
|
||||
char line[TOR_ADDR_BUF_LEN + 32];
|
||||
|
||||
tor_assert(first_redundant_entry < smartlist_len(*dest));
|
||||
p = smartlist_get(*dest, first_redundant_entry);
|
||||
/* since we've already parsed the policy into an addr_policy_t struct,
|
||||
* we might not log exactly what the user typed in */
|
||||
policy_write_item(line, TOR_ADDR_BUF_LEN + 32, p, 0);
|
||||
log_warn(LD_DIR, "Exit policy '%s' and all following policies are "
|
||||
"redundant, as it follows accept/reject *:* rules for both "
|
||||
"IPv4 and IPv6. They will be removed from the exit policy. (Use "
|
||||
"accept/reject *:* as the last entry in any exit policy.)",
|
||||
line);
|
||||
}
|
||||
|
||||
if (add_default_policy) {
|
||||
append_exit_policy_string(dest, DEFAULT_EXIT_POLICY);
|
||||
} else {
|
||||
@ -1013,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;
|
||||
@ -1035,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
|
||||
@ -1056,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;
|
||||
@ -1079,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 =
|
||||
|
@ -3666,24 +3666,38 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos)
|
||||
* assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
|
||||
* ADDR_POLICY_REJECT) for items that specify no action.
|
||||
*
|
||||
* Returns NULL on policy errors.
|
||||
*
|
||||
* If there is a policy error, malformed_list is set to true if the entire
|
||||
* policy list should be discarded. Otherwise, it is set to false, and only
|
||||
* this item should be ignored - the rest of the policy list can continue to
|
||||
* be processed and used.
|
||||
*
|
||||
* The addr_policy_t returned by this function can have its address set to
|
||||
* AF_UNSPEC for '*'. Use policy_expand_unspec() to turn this into a pair
|
||||
* of AF_INET and AF_INET6 items.
|
||||
*/
|
||||
MOCK_IMPL(addr_policy_t *,
|
||||
router_parse_addr_policy_item_from_string,(const char *s, int assume_action))
|
||||
router_parse_addr_policy_item_from_string,(const char *s, int assume_action,
|
||||
int *malformed_list))
|
||||
{
|
||||
directory_token_t *tok = NULL;
|
||||
const char *cp, *eos;
|
||||
/* Longest possible policy is
|
||||
* "accept6 ffff:ffff:..255/ffff:...255:10000-65535",
|
||||
* which contains 2 max-length IPv6 addresses, plus 21 characters.
|
||||
* "accept6 ffff:ffff:..255/128:10000-65535",
|
||||
* which contains a max-length IPv6 address, plus 24 characters.
|
||||
* But note that there can be an arbitrary amount of space between the
|
||||
* accept and the address:mask/port element. */
|
||||
* accept and the address:mask/port element.
|
||||
* We don't need to multiply TOR_ADDR_BUF_LEN by 2, as there is only one
|
||||
* IPv6 address. But making the buffer shorter might cause valid long lines,
|
||||
* which parsed in previous versions, to fail to parse in new versions.
|
||||
* (These lines would have to have excessive amounts of whitespace.) */
|
||||
char line[TOR_ADDR_BUF_LEN*2 + 32];
|
||||
addr_policy_t *r;
|
||||
memarea_t *area = NULL;
|
||||
|
||||
tor_assert(malformed_list);
|
||||
|
||||
s = eat_whitespace(s);
|
||||
if ((*s == '*' || TOR_ISDIGIT(*s)) && assume_action >= 0) {
|
||||
if (tor_snprintf(line, sizeof(line), "%s %s",
|
||||
@ -3710,9 +3724,32 @@ router_parse_addr_policy_item_from_string,(const char *s, int assume_action))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Use the extended interpretation of accept/reject *,
|
||||
* expanding it into an IPv4 wildcard and an IPv6 wildcard.
|
||||
* Also permit *4 and *6 for IPv4 and IPv6 only wildcards. */
|
||||
r = router_parse_addr_policy(tok, TAPMP_EXTENDED_STAR);
|
||||
if (!r) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Ensure that accept6/reject6 fields are followed by IPv6 addresses.
|
||||
* AF_UNSPEC addresses are only permitted on the accept/reject field type.
|
||||
* Unlike descriptors, torrcs exit policy accept/reject can be followed by
|
||||
* either an IPv4 or IPv6 address. */
|
||||
if ((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
|
||||
tor_addr_family(&r->addr) != AF_INET6) {
|
||||
/* This is a non-fatal error, just ignore this one entry. */
|
||||
*malformed_list = 0;
|
||||
log_warn(LD_DIR, "IPv4 address '%s' with accept6/reject6 field type in "
|
||||
"exit policy. Ignoring, but continuing to parse rules. (Use "
|
||||
"accept/reject with IPv4 addresses.)",
|
||||
tok->n_args == 1 ? tok->args[0] : "");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
goto done;
|
||||
err:
|
||||
*malformed_list = 1;
|
||||
r = NULL;
|
||||
done:
|
||||
token_clear(tok);
|
||||
@ -3729,19 +3766,27 @@ static int
|
||||
router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
|
||||
{
|
||||
addr_policy_t *newe;
|
||||
/* Use the standard interpretation of accept/reject *, an IPv4 wildcard. */
|
||||
newe = router_parse_addr_policy(tok, 0);
|
||||
if (!newe)
|
||||
return -1;
|
||||
if (! router->exit_policy)
|
||||
router->exit_policy = smartlist_new();
|
||||
|
||||
/* Ensure that in descriptors, accept/reject fields are followed by
|
||||
* IPv4 addresses, and accept6/reject6 fields are followed by
|
||||
* IPv6 addresses. Unlike torrcs, descriptor exit policies do not permit
|
||||
* accept/reject followed by IPv6. */
|
||||
if (((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
|
||||
tor_addr_family(&newe->addr) == AF_INET)
|
||||
||
|
||||
((tok->tp == K_ACCEPT || tok->tp == K_REJECT) &&
|
||||
tor_addr_family(&newe->addr) == AF_INET6)) {
|
||||
/* There's nothing the user can do about other relays' descriptors,
|
||||
* so we don't provide usage advice here. */
|
||||
log_warn(LD_DIR, "Mismatch between field type and address type in exit "
|
||||
"policy");
|
||||
"policy '%s'. Discarding entire router descriptor.",
|
||||
tok->n_args == 1 ? tok->args[0] : "");
|
||||
addr_policy_free(newe);
|
||||
return -1;
|
||||
}
|
||||
@ -3751,8 +3796,11 @@ router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Given a K_ACCEPT or K_REJECT token and a router, create and return
|
||||
* a new exit_policy_t corresponding to the token. */
|
||||
/** Given a K_ACCEPT[6] or K_REJECT[6] token and a router, create and return
|
||||
* a new exit_policy_t corresponding to the token. If TAPMP_EXTENDED_STAR
|
||||
* is set in fmt_flags, K_ACCEPT6 and K_REJECT6 tokens followed by *
|
||||
* expand to IPv6-only policies, otherwise they expand to IPv4 and IPv6
|
||||
* policies */
|
||||
static addr_policy_t *
|
||||
router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags)
|
||||
{
|
||||
@ -3776,6 +3824,13 @@ router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags)
|
||||
else
|
||||
newe.policy_type = ADDR_POLICY_ACCEPT;
|
||||
|
||||
/* accept6/reject6 * produces an IPv6 wildcard address only.
|
||||
* (accept/reject * produces rules for IPv4 and IPv6 wildcard addresses.) */
|
||||
if ((fmt_flags & TAPMP_EXTENDED_STAR)
|
||||
&& (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6)) {
|
||||
fmt_flags |= TAPMP_STAR_IPV6_ONLY;
|
||||
}
|
||||
|
||||
if (tor_addr_parse_mask_ports(arg, fmt_flags, &newe.addr, &newe.maskbits,
|
||||
&newe.prt_min, &newe.prt_max) < 0) {
|
||||
log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg));
|
||||
@ -3785,9 +3840,12 @@ router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags)
|
||||
return addr_policy_get_canonical_entry(&newe);
|
||||
}
|
||||
|
||||
/** Parse an exit policy line of the format "accept/reject private:...".
|
||||
/** Parse an exit policy line of the format "accept[6]/reject[6] private:...".
|
||||
* This didn't exist until Tor 0.1.1.15, so nobody should generate it in
|
||||
* router descriptors until earlier versions are obsolete.
|
||||
*
|
||||
* accept/reject and accept6/reject6 private all produce rules for both
|
||||
* IPv4 and IPv6 addresses.
|
||||
*/
|
||||
static addr_policy_t *
|
||||
router_parse_addr_policy_private(directory_token_t *tok)
|
||||
@ -3817,6 +3875,13 @@ router_parse_addr_policy_private(directory_token_t *tok)
|
||||
result.prt_min = port_min;
|
||||
result.prt_max = port_max;
|
||||
|
||||
if (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) {
|
||||
log_warn(LD_GENERAL,
|
||||
"'%s' expands into rules which apply to all private IPv4 and "
|
||||
"IPv6 addresses. (Use accept/reject private:* for IPv4 and "
|
||||
"IPv6.)", tok->n_args == 1 ? tok->args[0] : "");
|
||||
}
|
||||
|
||||
return addr_policy_get_canonical_entry(&result);
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ extrainfo_t *extrainfo_parse_entry_from_string(const char *s, const char *end,
|
||||
int cache_copy, struct digest_ri_map_t *routermap,
|
||||
int *can_dl_again_out);
|
||||
MOCK_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
|
||||
(const char *s, int assume_action));
|
||||
(const char *s, int assume_action, int *malformed_list));
|
||||
version_status_t tor_version_is_obsolete(const char *myversion,
|
||||
const char *versionlist);
|
||||
int tor_version_as_new_as(const char *platform, const char *cutoff);
|
||||
|
@ -85,10 +85,13 @@ routerset_parse(routerset_t *target, const char *s, const char *description)
|
||||
int added_countries = 0;
|
||||
char *countryname;
|
||||
smartlist_t *list = smartlist_new();
|
||||
int malformed_list;
|
||||
smartlist_split_string(list, s, ",",
|
||||
SPLIT_SKIP_SPACE | SPLIT_IGNORE_BLANK, 0);
|
||||
SMARTLIST_FOREACH_BEGIN(list, char *, nick) {
|
||||
addr_policy_t *p;
|
||||
/* if it doesn't pass our validation, assume it's malformed */
|
||||
malformed_list = 1;
|
||||
if (is_legal_hexdigest(nick)) {
|
||||
char d[DIGEST_LEN];
|
||||
if (*nick == '$')
|
||||
@ -106,15 +109,21 @@ routerset_parse(routerset_t *target, const char *s, const char *description)
|
||||
added_countries = 1;
|
||||
} else if ((strchr(nick,'.') || strchr(nick, '*')) &&
|
||||
(p = router_parse_addr_policy_item_from_string(
|
||||
nick, ADDR_POLICY_REJECT))) {
|
||||
nick, ADDR_POLICY_REJECT,
|
||||
&malformed_list))) {
|
||||
log_debug(LD_CONFIG, "Adding address %s to %s", nick, description);
|
||||
smartlist_add(target->policies, p);
|
||||
} else {
|
||||
log_warn(LD_CONFIG, "Entry '%s' in %s is malformed.", nick,
|
||||
description);
|
||||
} else if (malformed_list) {
|
||||
log_warn(LD_CONFIG, "Entry '%s' in %s is malformed. Discarding entire"
|
||||
" list.", nick, description);
|
||||
r = -1;
|
||||
tor_free(nick);
|
||||
SMARTLIST_DEL_CURRENT(list, nick);
|
||||
} else {
|
||||
log_notice(LD_CONFIG, "Entry '%s' in %s is ignored. Using the"
|
||||
" remainder of the list.", nick, description);
|
||||
tor_free(nick);
|
||||
SMARTLIST_DEL_CURRENT(list, nick);
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(nick);
|
||||
policy_expand_unspec(&target->policies);
|
||||
|
@ -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);
|
||||
@ -77,18 +77,21 @@ test_policies_general(void *arg)
|
||||
int i;
|
||||
smartlist_t *policy = NULL, *policy2 = NULL, *policy3 = NULL,
|
||||
*policy4 = NULL, *policy5 = NULL, *policy6 = NULL,
|
||||
*policy7 = NULL;
|
||||
*policy7 = NULL, *policy8 = NULL, *policy9 = NULL,
|
||||
*policy10 = NULL, *policy11 = NULL, *policy12 = NULL;
|
||||
addr_policy_t *p;
|
||||
tor_addr_t tar;
|
||||
config_line_t line;
|
||||
smartlist_t *sm = NULL;
|
||||
char *policy_str = NULL;
|
||||
short_policy_t *short_parsed = NULL;
|
||||
int malformed_list = -1;
|
||||
(void)arg;
|
||||
|
||||
policy = smartlist_new();
|
||||
|
||||
p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",-1);
|
||||
p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
tt_int_op(ADDR_POLICY_REJECT,OP_EQ, p->policy_type);
|
||||
tor_addr_from_ipv4h(&tar, 0xc0a80000u);
|
||||
@ -112,68 +115,122 @@ 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);
|
||||
p = router_parse_addr_policy_item_from_string("reject *:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy3, p);
|
||||
p = router_parse_addr_policy_item_from_string("accept *:*",-1);
|
||||
p = router_parse_addr_policy_item_from_string("accept *:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy3, p);
|
||||
|
||||
policy4 = smartlist_new();
|
||||
p = router_parse_addr_policy_item_from_string("accept *:443",-1);
|
||||
p = router_parse_addr_policy_item_from_string("accept *:443", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy4, p);
|
||||
p = router_parse_addr_policy_item_from_string("accept *:443",-1);
|
||||
p = router_parse_addr_policy_item_from_string("accept *:443", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy4, p);
|
||||
|
||||
policy5 = smartlist_new();
|
||||
p = router_parse_addr_policy_item_from_string("reject 0.0.0.0/8:*",-1);
|
||||
p = router_parse_addr_policy_item_from_string("reject 0.0.0.0/8:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy5, p);
|
||||
p = router_parse_addr_policy_item_from_string("reject 169.254.0.0/16:*",-1);
|
||||
p = router_parse_addr_policy_item_from_string("reject 169.254.0.0/16:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy5, p);
|
||||
p = router_parse_addr_policy_item_from_string("reject 127.0.0.0/8:*",-1);
|
||||
p = router_parse_addr_policy_item_from_string("reject 127.0.0.0/8:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy5, p);
|
||||
p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",-1);
|
||||
p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",
|
||||
-1, &malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy5, p);
|
||||
p = router_parse_addr_policy_item_from_string("reject 10.0.0.0/8:*",-1);
|
||||
p = router_parse_addr_policy_item_from_string("reject 10.0.0.0/8:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy5, p);
|
||||
p = router_parse_addr_policy_item_from_string("reject 172.16.0.0/12:*",-1);
|
||||
p = router_parse_addr_policy_item_from_string("reject 172.16.0.0/12:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy5, p);
|
||||
p = router_parse_addr_policy_item_from_string("reject 80.190.250.90:*",-1);
|
||||
p = router_parse_addr_policy_item_from_string("reject 80.190.250.90:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy5, p);
|
||||
p = router_parse_addr_policy_item_from_string("reject *:1-65534",-1);
|
||||
p = router_parse_addr_policy_item_from_string("reject *:1-65534", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy5, p);
|
||||
p = router_parse_addr_policy_item_from_string("reject *:65535",-1);
|
||||
p = router_parse_addr_policy_item_from_string("reject *:65535", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy5, p);
|
||||
p = router_parse_addr_policy_item_from_string("accept *:1-65535",-1);
|
||||
p = router_parse_addr_policy_item_from_string("accept *:1-65535", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy5, p);
|
||||
|
||||
policy6 = smartlist_new();
|
||||
p = router_parse_addr_policy_item_from_string("accept 43.3.0.0/9:*",-1);
|
||||
p = router_parse_addr_policy_item_from_string("accept 43.3.0.0/9:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy6, p);
|
||||
|
||||
policy7 = smartlist_new();
|
||||
p = router_parse_addr_policy_item_from_string("accept 0.0.0.0/8:*",-1);
|
||||
p = router_parse_addr_policy_item_from_string("accept 0.0.0.0/8:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy7, p);
|
||||
|
||||
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,
|
||||
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,
|
||||
NULL, 0));
|
||||
|
||||
tt_assert(policy9);
|
||||
|
||||
/* accept6 * and reject6 * produce IPv6 wildcards only */
|
||||
policy10 = smartlist_new();
|
||||
p = router_parse_addr_policy_item_from_string("accept6 *:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy10, p);
|
||||
|
||||
policy11 = smartlist_new();
|
||||
p = router_parse_addr_policy_item_from_string("reject6 *:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p != NULL);
|
||||
smartlist_add(policy11, p);
|
||||
|
||||
tt_assert(!exit_policy_is_general_exit(policy));
|
||||
tt_assert(exit_policy_is_general_exit(policy2));
|
||||
tt_assert(!exit_policy_is_general_exit(NULL));
|
||||
@ -182,6 +239,10 @@ test_policies_general(void *arg)
|
||||
tt_assert(!exit_policy_is_general_exit(policy5));
|
||||
tt_assert(!exit_policy_is_general_exit(policy6));
|
||||
tt_assert(!exit_policy_is_general_exit(policy7));
|
||||
tt_assert(exit_policy_is_general_exit(policy8));
|
||||
tt_assert(exit_policy_is_general_exit(policy9));
|
||||
tt_assert(!exit_policy_is_general_exit(policy10));
|
||||
tt_assert(!exit_policy_is_general_exit(policy11));
|
||||
|
||||
tt_assert(cmp_addr_policies(policy, policy2));
|
||||
tt_assert(cmp_addr_policies(policy, NULL));
|
||||
@ -190,7 +251,12 @@ test_policies_general(void *arg)
|
||||
|
||||
tt_assert(!policy_is_reject_star(policy2, AF_INET));
|
||||
tt_assert(policy_is_reject_star(policy, AF_INET));
|
||||
tt_assert(policy_is_reject_star(policy10, AF_INET));
|
||||
tt_assert(!policy_is_reject_star(policy10, AF_INET6));
|
||||
tt_assert(policy_is_reject_star(policy11, AF_INET));
|
||||
tt_assert(policy_is_reject_star(policy11, AF_INET6));
|
||||
tt_assert(policy_is_reject_star(NULL, AF_INET));
|
||||
tt_assert(policy_is_reject_star(NULL, AF_INET6));
|
||||
|
||||
addr_policy_list_free(policy);
|
||||
policy = NULL;
|
||||
@ -202,7 +268,8 @@ test_policies_general(void *arg)
|
||||
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_ADD_DEFAULT, 0,
|
||||
NULL, 0));
|
||||
tt_assert(policy);
|
||||
|
||||
//test_streq(policy->string, "accept *:80");
|
||||
@ -297,6 +364,68 @@ test_policies_general(void *arg)
|
||||
TT_BAD_SHORT_POLICY("accept 1-,3");
|
||||
TT_BAD_SHORT_POLICY("accept 1-,3");
|
||||
|
||||
/* Make sure that IPv4 addresses are ignored in accept6/reject6 lines. */
|
||||
p = router_parse_addr_policy_item_from_string("accept6 1.2.3.4:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p == NULL);
|
||||
tt_assert(!malformed_list);
|
||||
|
||||
p = router_parse_addr_policy_item_from_string("reject6 2.4.6.0/24:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p == NULL);
|
||||
tt_assert(!malformed_list);
|
||||
|
||||
p = router_parse_addr_policy_item_from_string("accept6 *4:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p == NULL);
|
||||
tt_assert(!malformed_list);
|
||||
|
||||
/* Make sure malformed policies are detected as such. */
|
||||
p = router_parse_addr_policy_item_from_string("bad_token *4:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p == NULL);
|
||||
tt_assert(malformed_list);
|
||||
|
||||
p = router_parse_addr_policy_item_from_string("accept6 **:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p == NULL);
|
||||
tt_assert(malformed_list);
|
||||
|
||||
p = router_parse_addr_policy_item_from_string("accept */15:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p == NULL);
|
||||
tt_assert(malformed_list);
|
||||
|
||||
p = router_parse_addr_policy_item_from_string("reject6 */:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p == NULL);
|
||||
tt_assert(malformed_list);
|
||||
|
||||
p = router_parse_addr_policy_item_from_string("accept 127.0.0.1/33:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p == NULL);
|
||||
tt_assert(malformed_list);
|
||||
|
||||
p = router_parse_addr_policy_item_from_string("accept6 [::1]/129:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p == NULL);
|
||||
tt_assert(malformed_list);
|
||||
|
||||
p = router_parse_addr_policy_item_from_string("reject 8.8.8.8/-1:*", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p == NULL);
|
||||
tt_assert(malformed_list);
|
||||
|
||||
p = router_parse_addr_policy_item_from_string("reject 8.8.4.4:10-5", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p == NULL);
|
||||
tt_assert(malformed_list);
|
||||
|
||||
p = router_parse_addr_policy_item_from_string("reject 1.2.3.4:-1", -1,
|
||||
&malformed_list);
|
||||
tt_assert(p == NULL);
|
||||
tt_assert(malformed_list);
|
||||
|
||||
/* Test a too-long policy. */
|
||||
{
|
||||
int i;
|
||||
@ -347,6 +476,11 @@ test_policies_general(void *arg)
|
||||
addr_policy_list_free(policy5);
|
||||
addr_policy_list_free(policy6);
|
||||
addr_policy_list_free(policy7);
|
||||
addr_policy_list_free(policy8);
|
||||
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));
|
||||
@ -360,6 +494,7 @@ test_dump_exit_policy_to_string(void *arg)
|
||||
{
|
||||
char *ep;
|
||||
addr_policy_t *policy_entry;
|
||||
int malformed_list = -1;
|
||||
|
||||
routerinfo_t *ri = tor_malloc_zero(sizeof(routerinfo_t));
|
||||
|
||||
@ -376,7 +511,8 @@ test_dump_exit_policy_to_string(void *arg)
|
||||
ri->exit_policy = smartlist_new();
|
||||
ri->policy_is_reject_star = 0;
|
||||
|
||||
policy_entry = router_parse_addr_policy_item_from_string("accept *:*",-1);
|
||||
policy_entry = router_parse_addr_policy_item_from_string("accept *:*", -1,
|
||||
&malformed_list);
|
||||
|
||||
smartlist_add(ri->exit_policy,policy_entry);
|
||||
|
||||
@ -386,7 +522,8 @@ test_dump_exit_policy_to_string(void *arg)
|
||||
|
||||
tor_free(ep);
|
||||
|
||||
policy_entry = router_parse_addr_policy_item_from_string("reject *:25",-1);
|
||||
policy_entry = router_parse_addr_policy_item_from_string("reject *:25", -1,
|
||||
&malformed_list);
|
||||
|
||||
smartlist_add(ri->exit_policy,policy_entry);
|
||||
|
||||
@ -397,7 +534,8 @@ test_dump_exit_policy_to_string(void *arg)
|
||||
tor_free(ep);
|
||||
|
||||
policy_entry =
|
||||
router_parse_addr_policy_item_from_string("reject 8.8.8.8:*",-1);
|
||||
router_parse_addr_policy_item_from_string("reject 8.8.8.8:*", -1,
|
||||
&malformed_list);
|
||||
|
||||
smartlist_add(ri->exit_policy,policy_entry);
|
||||
|
||||
@ -407,7 +545,8 @@ test_dump_exit_policy_to_string(void *arg)
|
||||
tor_free(ep);
|
||||
|
||||
policy_entry =
|
||||
router_parse_addr_policy_item_from_string("reject6 [FC00::]/7:*",-1);
|
||||
router_parse_addr_policy_item_from_string("reject6 [FC00::]/7:*", -1,
|
||||
&malformed_list);
|
||||
|
||||
smartlist_add(ri->exit_policy,policy_entry);
|
||||
|
||||
@ -418,7 +557,8 @@ test_dump_exit_policy_to_string(void *arg)
|
||||
tor_free(ep);
|
||||
|
||||
policy_entry =
|
||||
router_parse_addr_policy_item_from_string("accept6 [c000::]/3:*",-1);
|
||||
router_parse_addr_policy_item_from_string("accept6 [c000::]/3:*", -1,
|
||||
&malformed_list);
|
||||
|
||||
smartlist_add(ri->exit_policy,policy_entry);
|
||||
|
||||
|
@ -430,7 +430,7 @@ NS(test_main)(void *arg)
|
||||
*/
|
||||
|
||||
NS_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
|
||||
(const char *s, int assume_action));
|
||||
(const char *s, int assume_action, int *malformed_list));
|
||||
|
||||
addr_policy_t *NS(mock_addr_policy);
|
||||
|
||||
@ -457,10 +457,13 @@ NS(test_main)(void *arg)
|
||||
}
|
||||
|
||||
addr_policy_t *
|
||||
NS(router_parse_addr_policy_item_from_string)(const char *s, int assume_action)
|
||||
NS(router_parse_addr_policy_item_from_string)(const char *s,
|
||||
int assume_action,
|
||||
int *malformed_list)
|
||||
{
|
||||
(void)s;
|
||||
(void)assume_action;
|
||||
(void)malformed_list;
|
||||
CALLED(router_parse_addr_policy_item_from_string)++;
|
||||
|
||||
return NS(mock_addr_policy);
|
||||
|
Loading…
Reference in New Issue
Block a user