mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Merge branch 'getinfo-private-exitpolicy-v4-squashed'
This commit is contained in:
+4
-5
@@ -562,7 +562,6 @@ static char *get_bindaddr_from_transport_listen_line(const char *line,
|
||||
static int parse_dir_authority_line(const char *line,
|
||||
dirinfo_type_t required_type,
|
||||
int validate_only);
|
||||
static void port_cfg_free(port_cfg_t *port);
|
||||
static int parse_ports(or_options_t *options, int validate_only,
|
||||
char **msg_out, int *n_ports_out,
|
||||
int *world_writable_control_socket);
|
||||
@@ -5737,7 +5736,7 @@ parse_dir_fallback_line(const char *line,
|
||||
}
|
||||
|
||||
/** Allocate and return a new port_cfg_t with reasonable defaults. */
|
||||
static port_cfg_t *
|
||||
STATIC port_cfg_t *
|
||||
port_cfg_new(size_t namelen)
|
||||
{
|
||||
tor_assert(namelen <= SIZE_T_CEILING - sizeof(port_cfg_t) - 1);
|
||||
@@ -5749,7 +5748,7 @@ port_cfg_new(size_t namelen)
|
||||
}
|
||||
|
||||
/** Free all storage held in <b>port</b> */
|
||||
static void
|
||||
STATIC void
|
||||
port_cfg_free(port_cfg_t *port)
|
||||
{
|
||||
tor_free(port);
|
||||
@@ -6673,8 +6672,8 @@ check_server_ports(const smartlist_t *ports,
|
||||
|
||||
/** Return a list of port_cfg_t for client ports parsed from the
|
||||
* options. */
|
||||
const smartlist_t *
|
||||
get_configured_ports(void)
|
||||
MOCK_IMPL(const smartlist_t *,
|
||||
get_configured_ports,(void))
|
||||
{
|
||||
if (!configured_ports)
|
||||
configured_ports = smartlist_new();
|
||||
|
||||
+3
-1
@@ -76,7 +76,7 @@ int write_to_data_subdir(const char* subdir, const char* fname,
|
||||
|
||||
int get_num_cpus(const or_options_t *options);
|
||||
|
||||
const smartlist_t *get_configured_ports(void);
|
||||
MOCK_DECL(const smartlist_t *,get_configured_ports,(void));
|
||||
int get_first_advertised_port_by_type_af(int listener_type,
|
||||
int address_family);
|
||||
#define get_primary_or_port() \
|
||||
@@ -140,6 +140,8 @@ smartlist_t *get_options_for_server_transport(const char *transport);
|
||||
extern struct config_format_t options_format;
|
||||
#endif
|
||||
|
||||
STATIC port_cfg_t *port_cfg_new(size_t namelen);
|
||||
STATIC void port_cfg_free(port_cfg_t *port);
|
||||
STATIC void or_options_free(or_options_t *options);
|
||||
STATIC int options_validate(or_options_t *old_options,
|
||||
or_options_t *options,
|
||||
|
||||
@@ -2562,6 +2562,12 @@ static const getinfo_item_t getinfo_items[] = {
|
||||
"v3 Networkstatus consensus as retrieved from a DirPort."),
|
||||
ITEM("exit-policy/default", policies,
|
||||
"The default value appended to the configured exit policy."),
|
||||
ITEM("exit-policy/reject-private/default", policies,
|
||||
"The default rules appended to the configured exit policy by"
|
||||
" ExitPolicyRejectPrivate."),
|
||||
ITEM("exit-policy/reject-private/relay", policies,
|
||||
"The relay-specific rules appended to the configured exit policy by"
|
||||
" ExitPolicyRejectPrivate."),
|
||||
ITEM("exit-policy/full", policies, "The entire exit policy of onion router"),
|
||||
ITEM("exit-policy/ipv4", policies, "IPv4 parts of exit policy"),
|
||||
ITEM("exit-policy/ipv6", policies, "IPv6 parts of exit policy"),
|
||||
|
||||
+323
-106
@@ -62,14 +62,15 @@ static const char *private_nets[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static int 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);
|
||||
static int policies_parse_exit_policy_internal(
|
||||
config_line_t *cfg,
|
||||
smartlist_t **dest,
|
||||
int ipv6_exit,
|
||||
int rejectprivate,
|
||||
const smartlist_t *configured_addresses,
|
||||
int reject_interface_addresses,
|
||||
int reject_configured_port_addresses,
|
||||
int add_default_policy);
|
||||
|
||||
/** Replace all "private" entries in *<b>policy</b> with their expanded
|
||||
* equivalents. */
|
||||
@@ -443,7 +444,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,NULL,0,&addr_policy)) {
|
||||
if (policies_parse_exit_policy_from_options(options,0,NULL,&addr_policy)) {
|
||||
REJECT("Error in ExitPolicy entry.");
|
||||
}
|
||||
|
||||
@@ -864,7 +865,7 @@ addr_policy_intersects(addr_policy_t *a, addr_policy_t *b)
|
||||
|
||||
/** Add the exit policy described by <b>more</b> to <b>policy</b>.
|
||||
*/
|
||||
static void
|
||||
STATIC void
|
||||
append_exit_policy_string(smartlist_t **policy, const char *more)
|
||||
{
|
||||
config_line_t tmp;
|
||||
@@ -881,6 +882,9 @@ append_exit_policy_string(smartlist_t **policy, const char *more)
|
||||
void
|
||||
addr_policy_append_reject_addr(smartlist_t **dest, const tor_addr_t *addr)
|
||||
{
|
||||
tor_assert(dest);
|
||||
tor_assert(addr);
|
||||
|
||||
addr_policy_t p, *add;
|
||||
memset(&p, 0, sizeof(p));
|
||||
p.policy_type = ADDR_POLICY_REJECT;
|
||||
@@ -893,6 +897,71 @@ addr_policy_append_reject_addr(smartlist_t **dest, const tor_addr_t *addr)
|
||||
if (!*dest)
|
||||
*dest = smartlist_new();
|
||||
smartlist_add(*dest, add);
|
||||
log_debug(LD_CONFIG, "Adding a reject ExitPolicy 'reject %s:*'",
|
||||
fmt_addr(addr));
|
||||
|
||||
}
|
||||
|
||||
/* Is addr public for the purposes of rejection? */
|
||||
static int
|
||||
tor_addr_is_public_for_reject(const tor_addr_t *addr)
|
||||
{
|
||||
return !tor_addr_is_null(addr) && !tor_addr_is_internal(addr, 0);
|
||||
}
|
||||
|
||||
/* Add "reject <b>addr</b>:*" to <b>dest</b>, creating the list as needed.
|
||||
* Filter the address, only adding an IPv4 reject rule if ipv4_rules
|
||||
* is true, and similarly for ipv6_rules. Check each address returns true for
|
||||
* tor_addr_is_public_for_reject before adding it.
|
||||
*/
|
||||
static void
|
||||
addr_policy_append_reject_addr_filter(smartlist_t **dest,
|
||||
const tor_addr_t *addr,
|
||||
int ipv4_rules,
|
||||
int ipv6_rules)
|
||||
{
|
||||
tor_assert(dest);
|
||||
tor_assert(addr);
|
||||
|
||||
/* Only reject IP addresses which are public */
|
||||
if (tor_addr_is_public_for_reject(addr)) {
|
||||
|
||||
/* Reject IPv4 addresses and IPv6 addresses based on the filters */
|
||||
int is_ipv4 = tor_addr_is_v4(addr);
|
||||
if ((is_ipv4 && ipv4_rules) || (!is_ipv4 && ipv6_rules)) {
|
||||
addr_policy_append_reject_addr(dest, addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Add "reject addr:*" to <b>dest</b>, for each addr in addrs, creating the
|
||||
* list as needed. */
|
||||
void
|
||||
addr_policy_append_reject_addr_list(smartlist_t **dest,
|
||||
const smartlist_t *addrs)
|
||||
{
|
||||
tor_assert(dest);
|
||||
tor_assert(addrs);
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, addr) {
|
||||
addr_policy_append_reject_addr(dest, addr);
|
||||
} SMARTLIST_FOREACH_END(addr);
|
||||
}
|
||||
|
||||
/** Add "reject addr:*" to <b>dest</b>, for each addr in addrs, creating the
|
||||
* list as needed. Filter using */
|
||||
static void
|
||||
addr_policy_append_reject_addr_list_filter(smartlist_t **dest,
|
||||
const smartlist_t *addrs,
|
||||
int ipv4_rules,
|
||||
int ipv6_rules)
|
||||
{
|
||||
tor_assert(dest);
|
||||
tor_assert(addrs);
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, addr) {
|
||||
addr_policy_append_reject_addr_filter(dest, addr, ipv4_rules, ipv6_rules);
|
||||
} SMARTLIST_FOREACH_END(addr);
|
||||
}
|
||||
|
||||
/** Detect and excise "dead code" from the policy *<b>dest</b>. */
|
||||
@@ -979,6 +1048,76 @@ exit_policy_remove_redundancies(smartlist_t *dest)
|
||||
}
|
||||
}
|
||||
|
||||
/** Reject private helper for policies_parse_exit_policy_internal: rejects
|
||||
* publicly routable addresses on this exit relay.
|
||||
*
|
||||
* Add reject entries to the linked list *dest:
|
||||
* - if configured_addresses is non-NULL, add entries that reject each
|
||||
* tor_addr_t* in the list as a destination.
|
||||
* - if reject_interface_addresses is true, add entries that reject each
|
||||
* public IPv4 and IPv6 address of each interface on this machine.
|
||||
* - if reject_configured_port_addresses is true, add entries that reject
|
||||
* each IPv4 and IPv6 address configured for a port.
|
||||
*
|
||||
* IPv6 entries are only added if ipv6_exit is true. (All IPv6 addresses are
|
||||
* already blocked by policies_parse_exit_policy_internal if ipv6_exit is
|
||||
* false.)
|
||||
*
|
||||
* The list *dest is created as needed.
|
||||
*/
|
||||
void
|
||||
policies_parse_exit_policy_reject_private(
|
||||
smartlist_t **dest,
|
||||
int ipv6_exit,
|
||||
const smartlist_t *configured_addresses,
|
||||
int reject_interface_addresses,
|
||||
int reject_configured_port_addresses)
|
||||
{
|
||||
tor_assert(dest);
|
||||
|
||||
/* Reject configured addresses, if they are from public netblocks. */
|
||||
if (configured_addresses) {
|
||||
addr_policy_append_reject_addr_list_filter(dest, configured_addresses,
|
||||
1, ipv6_exit);
|
||||
}
|
||||
|
||||
/* Reject configured port addresses, if they are from public netblocks. */
|
||||
if (reject_configured_port_addresses) {
|
||||
const smartlist_t *port_addrs = get_configured_ports();
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(port_addrs, port_cfg_t *, port) {
|
||||
|
||||
/* Only reject port IP addresses, not port unix sockets */
|
||||
if (!port->is_unix_addr) {
|
||||
addr_policy_append_reject_addr_filter(dest, &port->addr, 1, ipv6_exit);
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(port);
|
||||
}
|
||||
|
||||
/* Reject local addresses from public netblocks on any interface. */
|
||||
if (reject_interface_addresses) {
|
||||
smartlist_t *public_addresses = NULL;
|
||||
|
||||
/* Reject public IPv4 addresses on any interface */
|
||||
public_addresses = get_interface_address6_list(LOG_INFO, AF_INET, 0);
|
||||
addr_policy_append_reject_addr_list_filter(dest, public_addresses, 1, 0);
|
||||
free_interface_address6_list(public_addresses);
|
||||
|
||||
/* Don't look for IPv6 addresses if we're configured as IPv4-only */
|
||||
if (ipv6_exit) {
|
||||
/* Reject public IPv6 addresses on any interface */
|
||||
public_addresses = get_interface_address6_list(LOG_INFO, AF_INET6, 0);
|
||||
addr_policy_append_reject_addr_list_filter(dest, public_addresses, 0, 1);
|
||||
free_interface_address6_list(public_addresses);
|
||||
}
|
||||
}
|
||||
|
||||
/* If addresses were added multiple times, remove all but one of them. */
|
||||
if (*dest) {
|
||||
exit_policy_remove_redundancies(*dest);
|
||||
}
|
||||
}
|
||||
|
||||
#define DEFAULT_EXIT_POLICY \
|
||||
"reject *:25,reject *:119,reject *:135-139,reject *:445," \
|
||||
"reject *:563,reject *:1214,reject *:4661-4666," \
|
||||
@@ -986,16 +1125,12 @@ exit_policy_remove_redundancies(smartlist_t *dest)
|
||||
|
||||
/** 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>ipv6_exit</b> is false, 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.
|
||||
* - prepend entries that reject publicly routable addresses on this exit
|
||||
* relay by calling policies_parse_exit_policy_reject_private
|
||||
*
|
||||
* If cfg doesn't end in an absolute accept or reject and if
|
||||
* <b>add_default_policy</b> is true, add the default exit
|
||||
@@ -1008,12 +1143,13 @@ exit_policy_remove_redundancies(smartlist_t *dest)
|
||||
* see router_add_exit_policy.
|
||||
*/
|
||||
static int
|
||||
policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest,
|
||||
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,
|
||||
const smartlist_t *configured_addresses,
|
||||
int reject_interface_addresses,
|
||||
int reject_configured_port_addresses,
|
||||
int add_default_policy)
|
||||
{
|
||||
if (!ipv6_exit) {
|
||||
@@ -1022,69 +1158,12 @@ policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest,
|
||||
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);
|
||||
}
|
||||
}
|
||||
/* Reject IPv4 and IPv6 publicly routable addresses on this exit relay */
|
||||
policies_parse_exit_policy_reject_private(
|
||||
dest, ipv6_exit,
|
||||
configured_addresses,
|
||||
reject_interface_addresses,
|
||||
reject_configured_port_addresses);
|
||||
}
|
||||
if (parse_addr_policy(cfg, dest, -1))
|
||||
return -1;
|
||||
@@ -1167,12 +1246,8 @@ policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest,
|
||||
* 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.
|
||||
* - prepend entries that reject publicly routable addresses on this exit
|
||||
* relay by calling policies_parse_exit_policy_internal
|
||||
*
|
||||
* If <b>EXIT_POLICY_ADD_DEFAULT</b> bit is set in <b>options</b>, append
|
||||
* default exit policy entries to <b>result</b> smartlist.
|
||||
@@ -1180,9 +1255,7 @@ policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest,
|
||||
int
|
||||
policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
|
||||
exit_policy_parser_cfg_t options,
|
||||
uint32_t local_address,
|
||||
tor_addr_t *ipv6_local_address,
|
||||
int reject_interface_addresses)
|
||||
const smartlist_t *configured_addresses)
|
||||
{
|
||||
int ipv6_enabled = (options & EXIT_POLICY_IPV6_ENABLED) ? 1 : 0;
|
||||
int reject_private = (options & EXIT_POLICY_REJECT_PRIVATE) ? 1 : 0;
|
||||
@@ -1190,12 +1263,51 @@ 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,
|
||||
configured_addresses,
|
||||
reject_private,
|
||||
reject_private,
|
||||
add_default);
|
||||
}
|
||||
|
||||
/** Helper function that adds addr to a smartlist as long as it is non-NULL
|
||||
* and not tor_addr_is_null(). */
|
||||
static void
|
||||
policies_add_addr_to_smartlist(smartlist_t *addr_list, const tor_addr_t *addr)
|
||||
{
|
||||
if (addr && !tor_addr_is_null(addr)) {
|
||||
smartlist_add(addr_list, (void *)addr);
|
||||
}
|
||||
}
|
||||
|
||||
/** Helper function that adds ipv4h_addr to a smartlist as a tor_addr_t *,
|
||||
* by converting it to a tor_addr_t and passing it to
|
||||
* policies_add_addr_to_smartlist. */
|
||||
static void
|
||||
policies_add_ipv4h_to_smartlist(smartlist_t *addr_list, uint32_t ipv4h_addr)
|
||||
{
|
||||
if (ipv4h_addr) {
|
||||
tor_addr_t ipv4_tor_addr;
|
||||
tor_addr_from_ipv4h(&ipv4_tor_addr, ipv4h_addr);
|
||||
policies_add_addr_to_smartlist(addr_list, (void *)&ipv4_tor_addr);
|
||||
}
|
||||
}
|
||||
|
||||
/** Helper function that adds or_options->OutboundBindAddressIPv[4|6]_ to a
|
||||
* smartlist as a tor_addr_t *, as long as or_options is non-NULL,
|
||||
* by passing them to policies_add_addr_to_smartlist. */
|
||||
static void
|
||||
policies_add_outbound_addresses_to_smartlist(smartlist_t *addr_list,
|
||||
const or_options_t *or_options)
|
||||
{
|
||||
if (or_options) {
|
||||
policies_add_addr_to_smartlist(addr_list,
|
||||
&or_options->OutboundBindAddressIPv4_);
|
||||
policies_add_addr_to_smartlist(addr_list,
|
||||
&or_options->OutboundBindAddressIPv6_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Parse <b>ExitPolicy</b> member of <b>or_options</b> into <b>result</b>
|
||||
* smartlist.
|
||||
* If <b>or_options->IPv6Exit</b> is false, prepend an entry that
|
||||
@@ -1205,11 +1317,13 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
|
||||
* - 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.
|
||||
* add it to the list of configured addresses.
|
||||
* - if ipv6_local_address is non-NULL, and not the null tor_addr_t, add it
|
||||
* to the list of configured addresses.
|
||||
* - if or_options->OutboundBindAddressIPv4_ is not the null tor_addr_t, add
|
||||
* it to the list of configured addresses.
|
||||
* - if or_options->OutboundBindAddressIPv6_ is not the null tor_addr_t, add
|
||||
* it to the list of configured addresses.
|
||||
*
|
||||
* If <b>or_options->BridgeRelay</b> is false, append entries of default
|
||||
* Tor exit policy into <b>result</b> smartlist.
|
||||
@@ -1220,18 +1334,21 @@ 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,
|
||||
const tor_addr_t *ipv6_local_address,
|
||||
smartlist_t **result)
|
||||
{
|
||||
exit_policy_parser_cfg_t parser_cfg = 0;
|
||||
smartlist_t *configured_addresses = smartlist_new();
|
||||
int rv = 0;
|
||||
|
||||
/* Short-circuit for non-exit relays */
|
||||
if (or_options->ExitRelay == 0) {
|
||||
append_exit_policy_string(result, "reject *4:*");
|
||||
append_exit_policy_string(result, "reject *6:*");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Configure the parser */
|
||||
if (or_options->IPv6Exit) {
|
||||
parser_cfg |= EXIT_POLICY_IPV6_ENABLED;
|
||||
}
|
||||
@@ -1244,10 +1361,20 @@ policies_parse_exit_policy_from_options(const or_options_t *or_options,
|
||||
parser_cfg |= EXIT_POLICY_ADD_DEFAULT;
|
||||
}
|
||||
|
||||
return policies_parse_exit_policy(or_options->ExitPolicy,result,
|
||||
parser_cfg,local_address,
|
||||
ipv6_local_address,
|
||||
reject_interface_addresses);
|
||||
/* Add the configured addresses to the tor_addr_t* list */
|
||||
policies_add_ipv4h_to_smartlist(configured_addresses, local_address);
|
||||
policies_add_addr_to_smartlist(configured_addresses, ipv6_local_address);
|
||||
policies_add_outbound_addresses_to_smartlist(configured_addresses,
|
||||
or_options);
|
||||
|
||||
rv = policies_parse_exit_policy(or_options->ExitPolicy, result, parser_cfg,
|
||||
configured_addresses);
|
||||
|
||||
/* We don't need to free the pointers in this list, they are either constant
|
||||
* or locally scoped. */
|
||||
smartlist_free(configured_addresses);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** Add "reject *:*" to the end of the policy in *<b>dest</b>, allocating
|
||||
@@ -1934,6 +2061,53 @@ compare_tor_addr_to_node_policy(const tor_addr_t *addr, uint16_t port,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given <b>policy_list</b>, a list of addr_policy_t, produce a string
|
||||
* representation of the list.
|
||||
* If <b>include_ipv4</b> is true, include IPv4 entries.
|
||||
* If <b>include_ipv6</b> is true, include IPv6 entries.
|
||||
*/
|
||||
char *
|
||||
policy_dump_to_string(const smartlist_t *policy_list,
|
||||
int include_ipv4,
|
||||
int include_ipv6)
|
||||
{
|
||||
smartlist_t *policy_string_list;
|
||||
char *policy_string = NULL;
|
||||
|
||||
policy_string_list = smartlist_new();
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(policy_list, addr_policy_t *, tmpe) {
|
||||
char *pbuf;
|
||||
int bytes_written_to_pbuf;
|
||||
if ((tor_addr_family(&tmpe->addr) == AF_INET6) && (!include_ipv6)) {
|
||||
continue; /* Don't include IPv6 parts of address policy */
|
||||
}
|
||||
if ((tor_addr_family(&tmpe->addr) == AF_INET) && (!include_ipv4)) {
|
||||
continue; /* Don't include IPv4 parts of address policy */
|
||||
}
|
||||
|
||||
pbuf = tor_malloc(POLICY_BUF_LEN);
|
||||
bytes_written_to_pbuf = policy_write_item(pbuf,POLICY_BUF_LEN, tmpe, 1);
|
||||
|
||||
if (bytes_written_to_pbuf < 0) {
|
||||
log_warn(LD_BUG, "policy_dump_to_string ran out of room!");
|
||||
tor_free(pbuf);
|
||||
goto done;
|
||||
}
|
||||
|
||||
smartlist_add(policy_string_list,pbuf);
|
||||
} SMARTLIST_FOREACH_END(tmpe);
|
||||
|
||||
policy_string = smartlist_join_strings(policy_string_list, "\n", 0, NULL);
|
||||
|
||||
done:
|
||||
SMARTLIST_FOREACH(policy_string_list, char *, str, tor_free(str));
|
||||
smartlist_free(policy_string_list);
|
||||
|
||||
return policy_string;
|
||||
}
|
||||
|
||||
/** Implementation for GETINFO control command: knows the answer for questions
|
||||
* about "exit-policy/..." */
|
||||
int
|
||||
@@ -1945,6 +2119,49 @@ getinfo_helper_policies(control_connection_t *conn,
|
||||
(void) errmsg;
|
||||
if (!strcmp(question, "exit-policy/default")) {
|
||||
*answer = tor_strdup(DEFAULT_EXIT_POLICY);
|
||||
} else if (!strcmp(question, "exit-policy/reject-private/default")) {
|
||||
smartlist_t *private_policy_strings;
|
||||
const char **priv = private_nets;
|
||||
|
||||
private_policy_strings = smartlist_new();
|
||||
|
||||
while (*priv != NULL) {
|
||||
/* IPv6 addresses are in "[]" and contain ":",
|
||||
* IPv4 addresses are not in "[]" and contain "." */
|
||||
smartlist_add_asprintf(private_policy_strings, "reject %s:*", *priv);
|
||||
priv++;
|
||||
}
|
||||
|
||||
*answer = smartlist_join_strings(private_policy_strings,
|
||||
",", 0, NULL);
|
||||
|
||||
SMARTLIST_FOREACH(private_policy_strings, char *, str, tor_free(str));
|
||||
smartlist_free(private_policy_strings);
|
||||
} else if (!strcmp(question, "exit-policy/reject-private/relay")) {
|
||||
const or_options_t *options = get_options();
|
||||
const routerinfo_t *me = router_get_my_routerinfo();
|
||||
smartlist_t *private_policy_list = smartlist_new();
|
||||
smartlist_t *configured_addresses = smartlist_new();
|
||||
|
||||
if (!me) {
|
||||
*errmsg = "router_get_my_routerinfo returned NULL";
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Add the configured addresses to the tor_addr_t* list */
|
||||
policies_add_ipv4h_to_smartlist(configured_addresses, me->addr);
|
||||
policies_add_addr_to_smartlist(configured_addresses, &me->ipv6_addr);
|
||||
policies_add_outbound_addresses_to_smartlist(configured_addresses,
|
||||
options);
|
||||
|
||||
policies_parse_exit_policy_reject_private(
|
||||
&private_policy_list,
|
||||
options->IPv6Exit,
|
||||
configured_addresses,
|
||||
1, 1);
|
||||
*answer = policy_dump_to_string(private_policy_list, 1, 1);
|
||||
|
||||
addr_policy_list_free(private_policy_list);
|
||||
} else if (!strcmpstart(question, "exit-policy/")) {
|
||||
const routerinfo_t *me = router_get_my_routerinfo();
|
||||
|
||||
|
||||
+21
-9
@@ -44,26 +44,34 @@ addr_policy_t *addr_policy_get_canonical_entry(addr_policy_t *ent);
|
||||
int cmp_addr_policies(smartlist_t *a, smartlist_t *b);
|
||||
MOCK_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy,
|
||||
(const tor_addr_t *addr, uint16_t port, const smartlist_t *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_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_from_options(
|
||||
const or_options_t *or_options,
|
||||
uint32_t local_address,
|
||||
const tor_addr_t *ipv6_local_address,
|
||||
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,
|
||||
tor_addr_t *ipv6_local_address,
|
||||
int reject_interface_addresses);
|
||||
const smartlist_t *configured_addresses);
|
||||
void policies_parse_exit_policy_reject_private(
|
||||
smartlist_t **dest,
|
||||
int ipv6_exit,
|
||||
const smartlist_t *configured_addresses,
|
||||
int reject_interface_addresses,
|
||||
int reject_configured_port_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);
|
||||
void addr_policy_append_reject_addr_list(smartlist_t **dest,
|
||||
const smartlist_t *addrs);
|
||||
void policies_set_node_exitpolicy_to_reject_all(node_t *exitrouter);
|
||||
int exit_policy_is_general_exit(smartlist_t *policy);
|
||||
int policy_is_reject_star(const smartlist_t *policy, sa_family_t family);
|
||||
char * policy_dump_to_string(const smartlist_t *policy_list,
|
||||
int include_ipv4,
|
||||
int include_ipv6);
|
||||
int getinfo_helper_policies(control_connection_t *conn,
|
||||
const char *question, char **answer,
|
||||
const char **errmsg);
|
||||
@@ -84,5 +92,9 @@ addr_policy_result_t compare_tor_addr_to_short_policy(
|
||||
const tor_addr_t *addr, uint16_t port,
|
||||
const short_policy_t *policy);
|
||||
|
||||
#ifdef POLICIES_PRIVATE
|
||||
void append_exit_policy_string(smartlist_t **policy, const char *more);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+4
-35
@@ -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,&ri->ipv6_addr,1,
|
||||
policies_parse_exit_policy_from_options(options,ri->addr,&ri->ipv6_addr,
|
||||
&ri->exit_policy);
|
||||
}
|
||||
ri->policy_is_reject_star =
|
||||
@@ -2728,44 +2728,13 @@ router_dump_exit_policy_to_string(const routerinfo_t *router,
|
||||
int include_ipv4,
|
||||
int include_ipv6)
|
||||
{
|
||||
smartlist_t *exit_policy_strings;
|
||||
char *policy_string = NULL;
|
||||
|
||||
if ((!router->exit_policy) || (router->policy_is_reject_star)) {
|
||||
return tor_strdup("reject *:*");
|
||||
}
|
||||
|
||||
exit_policy_strings = smartlist_new();
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(router->exit_policy, addr_policy_t *, tmpe) {
|
||||
char *pbuf;
|
||||
int bytes_written_to_pbuf;
|
||||
if ((tor_addr_family(&tmpe->addr) == AF_INET6) && (!include_ipv6)) {
|
||||
continue; /* Don't include IPv6 parts of address policy */
|
||||
}
|
||||
if ((tor_addr_family(&tmpe->addr) == AF_INET) && (!include_ipv4)) {
|
||||
continue; /* Don't include IPv4 parts of address policy */
|
||||
}
|
||||
|
||||
pbuf = tor_malloc(POLICY_BUF_LEN);
|
||||
bytes_written_to_pbuf = policy_write_item(pbuf,POLICY_BUF_LEN, tmpe, 1);
|
||||
|
||||
if (bytes_written_to_pbuf < 0) {
|
||||
log_warn(LD_BUG, "router_dump_exit_policy_to_string ran out of room!");
|
||||
tor_free(pbuf);
|
||||
goto done;
|
||||
}
|
||||
|
||||
smartlist_add(exit_policy_strings,pbuf);
|
||||
} SMARTLIST_FOREACH_END(tmpe);
|
||||
|
||||
policy_string = smartlist_join_strings(exit_policy_strings, "\n", 0, NULL);
|
||||
|
||||
done:
|
||||
SMARTLIST_FOREACH(exit_policy_strings, char *, str, tor_free(str));
|
||||
smartlist_free(exit_policy_strings);
|
||||
|
||||
return policy_string;
|
||||
return policy_dump_to_string(router->exit_policy,
|
||||
include_ipv4,
|
||||
include_ipv6);
|
||||
}
|
||||
|
||||
/** Copy the primary (IPv4) OR port (IP address and TCP port) for
|
||||
|
||||
+398
-12
@@ -2,8 +2,11 @@
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
#include "or.h"
|
||||
#define CONFIG_PRIVATE
|
||||
#include "config.h"
|
||||
#include "router.h"
|
||||
#include "routerparse.h"
|
||||
#define POLICIES_PRIVATE
|
||||
#include "policies.h"
|
||||
#include "test.h"
|
||||
|
||||
@@ -49,7 +52,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, NULL, 0);
|
||||
EXIT_POLICY_ADD_DEFAULT, NULL);
|
||||
tt_int_op(r,OP_EQ, 0);
|
||||
|
||||
summary = policy_summarize(policy, AF_INET);
|
||||
@@ -80,7 +83,8 @@ test_policies_general(void *arg)
|
||||
*policy7 = NULL, *policy8 = NULL, *policy9 = NULL,
|
||||
*policy10 = NULL, *policy11 = NULL, *policy12 = NULL;
|
||||
addr_policy_t *p;
|
||||
tor_addr_t tar;
|
||||
tor_addr_t tar, tar2;
|
||||
smartlist_t *addr_list = NULL;
|
||||
config_line_t line;
|
||||
smartlist_t *sm = NULL;
|
||||
char *policy_str = NULL;
|
||||
@@ -115,17 +119,22 @@ 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,
|
||||
NULL, 0));
|
||||
EXIT_POLICY_ADD_DEFAULT, NULL));
|
||||
|
||||
tt_assert(policy2);
|
||||
|
||||
tor_addr_parse(&tar, "[2000::1234]");
|
||||
tor_addr_from_ipv4h(&tar, 0x0306090cu);
|
||||
tor_addr_parse(&tar2, "[2000::1234]");
|
||||
addr_list = smartlist_new();
|
||||
smartlist_add(addr_list, &tar);
|
||||
smartlist_add(addr_list, &tar2);
|
||||
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));
|
||||
addr_list));
|
||||
smartlist_free(addr_list);
|
||||
addr_list = NULL;
|
||||
|
||||
tt_assert(policy12);
|
||||
|
||||
@@ -206,15 +215,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,
|
||||
NULL, 0));
|
||||
EXIT_POLICY_ADD_DEFAULT,
|
||||
NULL));
|
||||
|
||||
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));
|
||||
EXIT_POLICY_ADD_DEFAULT,
|
||||
NULL));
|
||||
|
||||
tt_assert(policy9);
|
||||
|
||||
@@ -268,8 +277,7 @@ 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,
|
||||
NULL, 0));
|
||||
EXIT_POLICY_ADD_DEFAULT, NULL));
|
||||
tt_assert(policy);
|
||||
|
||||
//test_streq(policy->string, "accept *:80");
|
||||
@@ -489,6 +497,245 @@ test_policies_general(void *arg)
|
||||
short_policy_free(short_parsed);
|
||||
}
|
||||
|
||||
/** Helper: Check that policy_list contains address */
|
||||
static int
|
||||
test_policy_has_address_helper(const smartlist_t *policy_list,
|
||||
const tor_addr_t *addr)
|
||||
{
|
||||
int found = 0;
|
||||
|
||||
tt_assert(policy_list);
|
||||
tt_assert(addr);
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(policy_list, addr_policy_t*, p) {
|
||||
if (tor_addr_eq(&p->addr, addr)) {
|
||||
found = 1;
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(p);
|
||||
|
||||
return found;
|
||||
|
||||
done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_IPV4_ADDR (0x01020304)
|
||||
#define TEST_IPV6_ADDR ("2002::abcd")
|
||||
|
||||
/** Run unit tests for rejecting the configured addresses on this exit relay
|
||||
* using policies_parse_exit_policy_reject_private */
|
||||
static void
|
||||
test_policies_reject_exit_address(void *arg)
|
||||
{
|
||||
smartlist_t *policy = NULL;
|
||||
tor_addr_t ipv4_addr, ipv6_addr;
|
||||
smartlist_t *ipv4_list, *ipv6_list, *both_list, *dupl_list;
|
||||
(void)arg;
|
||||
|
||||
tor_addr_from_ipv4h(&ipv4_addr, TEST_IPV4_ADDR);
|
||||
tor_addr_parse(&ipv6_addr, TEST_IPV6_ADDR);
|
||||
|
||||
ipv4_list = smartlist_new();
|
||||
ipv6_list = smartlist_new();
|
||||
both_list = smartlist_new();
|
||||
dupl_list = smartlist_new();
|
||||
|
||||
smartlist_add(ipv4_list, &ipv4_addr);
|
||||
smartlist_add(both_list, &ipv4_addr);
|
||||
smartlist_add(dupl_list, &ipv4_addr);
|
||||
smartlist_add(dupl_list, &ipv4_addr);
|
||||
smartlist_add(dupl_list, &ipv4_addr);
|
||||
|
||||
smartlist_add(ipv6_list, &ipv6_addr);
|
||||
smartlist_add(both_list, &ipv6_addr);
|
||||
smartlist_add(dupl_list, &ipv6_addr);
|
||||
smartlist_add(dupl_list, &ipv6_addr);
|
||||
|
||||
/* IPv4-Only Exits */
|
||||
|
||||
/* test that IPv4 addresses are rejected on an IPv4-only exit */
|
||||
policies_parse_exit_policy_reject_private(&policy, 0, ipv4_list, 0, 0);
|
||||
tt_assert(policy);
|
||||
tt_assert(smartlist_len(policy) == 1);
|
||||
tt_assert(test_policy_has_address_helper(policy, &ipv4_addr));
|
||||
addr_policy_list_free(policy);
|
||||
policy = NULL;
|
||||
|
||||
/* test that IPv6 addresses are NOT rejected on an IPv4-only exit
|
||||
* (all IPv6 addresses are rejected by policies_parse_exit_policy_internal
|
||||
* on IPv4-only exits, so policies_parse_exit_policy_reject_private doesn't
|
||||
* need to do anything) */
|
||||
policies_parse_exit_policy_reject_private(&policy, 0, ipv6_list, 0, 0);
|
||||
tt_assert(policy == NULL);
|
||||
|
||||
/* test that only IPv4 addresses are rejected on an IPv4-only exit */
|
||||
policies_parse_exit_policy_reject_private(&policy, 0, both_list, 0, 0);
|
||||
tt_assert(policy);
|
||||
tt_assert(smartlist_len(policy) == 1);
|
||||
tt_assert(test_policy_has_address_helper(policy, &ipv4_addr));
|
||||
addr_policy_list_free(policy);
|
||||
policy = NULL;
|
||||
|
||||
/* Test that lists with duplicate entries produce the same results */
|
||||
policies_parse_exit_policy_reject_private(&policy, 0, dupl_list, 0, 0);
|
||||
tt_assert(policy);
|
||||
tt_assert(smartlist_len(policy) == 1);
|
||||
tt_assert(test_policy_has_address_helper(policy, &ipv4_addr));
|
||||
addr_policy_list_free(policy);
|
||||
policy = NULL;
|
||||
|
||||
/* IPv4/IPv6 Exits */
|
||||
|
||||
/* test that IPv4 addresses are rejected on an IPv4/IPv6 exit */
|
||||
policies_parse_exit_policy_reject_private(&policy, 1, ipv4_list, 0, 0);
|
||||
tt_assert(policy);
|
||||
tt_assert(smartlist_len(policy) == 1);
|
||||
tt_assert(test_policy_has_address_helper(policy, &ipv4_addr));
|
||||
addr_policy_list_free(policy);
|
||||
policy = NULL;
|
||||
|
||||
/* test that IPv6 addresses are rejected on an IPv4/IPv6 exit */
|
||||
policies_parse_exit_policy_reject_private(&policy, 1, ipv6_list, 0, 0);
|
||||
tt_assert(policy);
|
||||
tt_assert(smartlist_len(policy) == 1);
|
||||
tt_assert(test_policy_has_address_helper(policy, &ipv6_addr));
|
||||
addr_policy_list_free(policy);
|
||||
policy = NULL;
|
||||
|
||||
/* test that IPv4 and IPv6 addresses are rejected on an IPv4/IPv6 exit */
|
||||
policies_parse_exit_policy_reject_private(&policy, 1, both_list, 0, 0);
|
||||
tt_assert(policy);
|
||||
tt_assert(smartlist_len(policy) == 2);
|
||||
tt_assert(test_policy_has_address_helper(policy, &ipv4_addr));
|
||||
tt_assert(test_policy_has_address_helper(policy, &ipv6_addr));
|
||||
addr_policy_list_free(policy);
|
||||
policy = NULL;
|
||||
|
||||
/* Test that lists with duplicate entries produce the same results */
|
||||
policies_parse_exit_policy_reject_private(&policy, 1, dupl_list, 0, 0);
|
||||
tt_assert(policy);
|
||||
tt_assert(smartlist_len(policy) == 2);
|
||||
tt_assert(test_policy_has_address_helper(policy, &ipv4_addr));
|
||||
tt_assert(test_policy_has_address_helper(policy, &ipv6_addr));
|
||||
addr_policy_list_free(policy);
|
||||
policy = NULL;
|
||||
|
||||
done:
|
||||
addr_policy_list_free(policy);
|
||||
smartlist_free(ipv4_list);
|
||||
smartlist_free(ipv6_list);
|
||||
smartlist_free(both_list);
|
||||
smartlist_free(dupl_list);
|
||||
}
|
||||
|
||||
static smartlist_t *test_configured_ports = NULL;
|
||||
const smartlist_t *mock_get_configured_ports(void);
|
||||
|
||||
/** Returns test_configured_ports */
|
||||
const smartlist_t *
|
||||
mock_get_configured_ports(void)
|
||||
{
|
||||
return test_configured_ports;
|
||||
}
|
||||
|
||||
/** Run unit tests for rejecting publicly routable configured port addresses
|
||||
* on this exit relay using policies_parse_exit_policy_reject_private */
|
||||
static void
|
||||
test_policies_reject_port_address(void *arg)
|
||||
{
|
||||
smartlist_t *policy = NULL;
|
||||
port_cfg_t *ipv4_port = NULL;
|
||||
port_cfg_t *ipv6_port = NULL;
|
||||
(void)arg;
|
||||
|
||||
test_configured_ports = smartlist_new();
|
||||
|
||||
ipv4_port = port_cfg_new(0);
|
||||
tor_addr_from_ipv4h(&ipv4_port->addr, TEST_IPV4_ADDR);
|
||||
smartlist_add(test_configured_ports, ipv4_port);
|
||||
|
||||
ipv6_port = port_cfg_new(0);
|
||||
tor_addr_parse(&ipv6_port->addr, TEST_IPV6_ADDR);
|
||||
smartlist_add(test_configured_ports, ipv6_port);
|
||||
|
||||
MOCK(get_configured_ports, mock_get_configured_ports);
|
||||
|
||||
/* test that an IPv4 port is rejected on an IPv4-only exit, but an IPv6 port
|
||||
* is NOT rejected (all IPv6 addresses are rejected by
|
||||
* policies_parse_exit_policy_internal on IPv4-only exits, so
|
||||
* policies_parse_exit_policy_reject_private doesn't need to do anything
|
||||
* with IPv6 addresses on IPv4-only exits) */
|
||||
policies_parse_exit_policy_reject_private(&policy, 0, NULL, 0, 1);
|
||||
tt_assert(policy);
|
||||
tt_assert(smartlist_len(policy) == 1);
|
||||
tt_assert(test_policy_has_address_helper(policy, &ipv4_port->addr));
|
||||
addr_policy_list_free(policy);
|
||||
policy = NULL;
|
||||
|
||||
/* test that IPv4 and IPv6 ports are rejected on an IPv4/IPv6 exit */
|
||||
policies_parse_exit_policy_reject_private(&policy, 1, NULL, 0, 1);
|
||||
tt_assert(policy);
|
||||
tt_assert(smartlist_len(policy) == 2);
|
||||
tt_assert(test_policy_has_address_helper(policy, &ipv4_port->addr));
|
||||
tt_assert(test_policy_has_address_helper(policy, &ipv6_port->addr));
|
||||
addr_policy_list_free(policy);
|
||||
policy = NULL;
|
||||
|
||||
done:
|
||||
addr_policy_list_free(policy);
|
||||
if (test_configured_ports) {
|
||||
SMARTLIST_FOREACH(test_configured_ports,
|
||||
port_cfg_t *, p, port_cfg_free(p));
|
||||
smartlist_free(test_configured_ports);
|
||||
test_configured_ports = NULL;
|
||||
}
|
||||
UNMOCK(get_configured_ports);
|
||||
}
|
||||
|
||||
#undef TEST_IPV4_ADDR
|
||||
#undef TEST_IPV6_ADDR
|
||||
|
||||
/** Run unit tests for rejecting publicly routable interface addresses on this
|
||||
* exit relay using policies_parse_exit_policy_reject_private */
|
||||
static void
|
||||
test_policies_reject_interface_address(void *arg)
|
||||
{
|
||||
smartlist_t *policy = NULL;
|
||||
smartlist_t *public_ipv4_addrs =
|
||||
get_interface_address6_list(LOG_INFO, AF_INET, 0);
|
||||
smartlist_t *public_ipv6_addrs =
|
||||
get_interface_address6_list(LOG_INFO, AF_INET6, 0);
|
||||
(void)arg;
|
||||
|
||||
/* test that no addresses are rejected when none are supplied/requested */
|
||||
policies_parse_exit_policy_reject_private(&policy, 0, NULL, 0, 0);
|
||||
tt_assert(policy == NULL);
|
||||
|
||||
/* test that only IPv4 interface addresses are rejected on an IPv4-only exit
|
||||
*/
|
||||
policies_parse_exit_policy_reject_private(&policy, 0, NULL, 1, 0);
|
||||
if (policy) {
|
||||
tt_assert(smartlist_len(policy) == smartlist_len(public_ipv4_addrs));
|
||||
addr_policy_list_free(policy);
|
||||
policy = NULL;
|
||||
}
|
||||
|
||||
/* test that IPv4 and IPv6 interface addresses are rejected on an IPv4/IPv6
|
||||
* exit */
|
||||
policies_parse_exit_policy_reject_private(&policy, 0, NULL, 1, 0);
|
||||
if (policy) {
|
||||
tt_assert(smartlist_len(policy) == (smartlist_len(public_ipv4_addrs)
|
||||
+ smartlist_len(public_ipv6_addrs)));
|
||||
addr_policy_list_free(policy);
|
||||
policy = NULL;
|
||||
}
|
||||
|
||||
done:
|
||||
addr_policy_list_free(policy);
|
||||
free_interface_address6_list(public_ipv4_addrs);
|
||||
free_interface_address6_list(public_ipv6_addrs);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dump_exit_policy_to_string(void *arg)
|
||||
{
|
||||
@@ -578,10 +825,149 @@ test_dump_exit_policy_to_string(void *arg)
|
||||
tor_free(ep);
|
||||
}
|
||||
|
||||
static routerinfo_t *mock_desc_routerinfo = NULL;
|
||||
const routerinfo_t *mock_router_get_my_routerinfo(void)
|
||||
{
|
||||
return mock_desc_routerinfo;
|
||||
}
|
||||
|
||||
#define DEFAULT_POLICY_STRING "reject *:*"
|
||||
#define TEST_IPV4_ADDR (0x02040608)
|
||||
#define TEST_IPV6_ADDR ("2003::ef01")
|
||||
|
||||
static or_options_t mock_options;
|
||||
|
||||
static const or_options_t *
|
||||
mock_get_options(void)
|
||||
{
|
||||
return &mock_options;
|
||||
}
|
||||
|
||||
/** Run unit tests for generating summary lines of exit policies */
|
||||
static void
|
||||
test_policies_getinfo_helper_policies(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int rv = 0;
|
||||
size_t ipv4_len = 0, ipv6_len = 0;
|
||||
char *answer = NULL;
|
||||
const char *errmsg = NULL;
|
||||
routerinfo_t mock_my_routerinfo;
|
||||
|
||||
rv = getinfo_helper_policies(NULL, "exit-policy/default", &answer, &errmsg);
|
||||
tt_assert(rv == 0);
|
||||
tt_assert(answer != NULL);
|
||||
tt_assert(strlen(answer) > 0);
|
||||
tor_free(answer);
|
||||
|
||||
rv = getinfo_helper_policies(NULL, "exit-policy/reject-private/default",
|
||||
&answer, &errmsg);
|
||||
tt_assert(rv == 0);
|
||||
tt_assert(answer != NULL);
|
||||
tt_assert(strlen(answer) > 0);
|
||||
tor_free(answer);
|
||||
|
||||
memset(&mock_my_routerinfo, 0, sizeof(routerinfo_t));
|
||||
MOCK(router_get_my_routerinfo, mock_router_get_my_routerinfo);
|
||||
mock_my_routerinfo.exit_policy = smartlist_new();
|
||||
mock_desc_routerinfo = &mock_my_routerinfo;
|
||||
|
||||
memset(&mock_options, 0, sizeof(or_options_t));
|
||||
MOCK(get_options, mock_get_options);
|
||||
|
||||
rv = getinfo_helper_policies(NULL, "exit-policy/reject-private/relay",
|
||||
&answer, &errmsg);
|
||||
tt_assert(rv == 0);
|
||||
tt_assert(answer != NULL);
|
||||
tt_assert(strlen(answer) == 0);
|
||||
tor_free(answer);
|
||||
|
||||
rv = getinfo_helper_policies(NULL, "exit-policy/ipv4", &answer,
|
||||
&errmsg);
|
||||
tt_assert(rv == 0);
|
||||
tt_assert(answer != NULL);
|
||||
ipv4_len = strlen(answer);
|
||||
tt_assert(ipv4_len == 0 || ipv4_len == strlen(DEFAULT_POLICY_STRING));
|
||||
tt_assert(ipv4_len == 0 || !strcasecmp(answer, DEFAULT_POLICY_STRING));
|
||||
tor_free(answer);
|
||||
|
||||
rv = getinfo_helper_policies(NULL, "exit-policy/ipv6", &answer,
|
||||
&errmsg);
|
||||
tt_assert(rv == 0);
|
||||
tt_assert(answer != NULL);
|
||||
ipv6_len = strlen(answer);
|
||||
tt_assert(ipv6_len == 0 || ipv6_len == strlen(DEFAULT_POLICY_STRING));
|
||||
tt_assert(ipv6_len == 0 || !strcasecmp(answer, DEFAULT_POLICY_STRING));
|
||||
tor_free(answer);
|
||||
|
||||
rv = getinfo_helper_policies(NULL, "exit-policy/full", &answer,
|
||||
&errmsg);
|
||||
tt_assert(rv == 0);
|
||||
tt_assert(answer != NULL);
|
||||
/* It's either empty or it's the default */
|
||||
tt_assert(strlen(answer) == 0 || !strcasecmp(answer, DEFAULT_POLICY_STRING));
|
||||
tor_free(answer);
|
||||
|
||||
mock_my_routerinfo.addr = TEST_IPV4_ADDR;
|
||||
tor_addr_parse(&mock_my_routerinfo.ipv6_addr, TEST_IPV6_ADDR);
|
||||
append_exit_policy_string(&mock_my_routerinfo.exit_policy, "accept *4:*");
|
||||
append_exit_policy_string(&mock_my_routerinfo.exit_policy, "reject *6:*");
|
||||
|
||||
mock_options.IPv6Exit = 1;
|
||||
tor_addr_from_ipv4h(&mock_options.OutboundBindAddressIPv4_, TEST_IPV4_ADDR);
|
||||
tor_addr_parse(&mock_options.OutboundBindAddressIPv6_, TEST_IPV6_ADDR);
|
||||
|
||||
rv = getinfo_helper_policies(NULL, "exit-policy/reject-private/relay",
|
||||
&answer, &errmsg);
|
||||
tt_assert(rv == 0);
|
||||
tt_assert(answer != NULL);
|
||||
tt_assert(strlen(answer) > 0);
|
||||
tor_free(answer);
|
||||
|
||||
rv = getinfo_helper_policies(NULL, "exit-policy/ipv4", &answer,
|
||||
&errmsg);
|
||||
tt_assert(rv == 0);
|
||||
tt_assert(answer != NULL);
|
||||
ipv4_len = strlen(answer);
|
||||
tt_assert(ipv4_len > 0);
|
||||
tor_free(answer);
|
||||
|
||||
rv = getinfo_helper_policies(NULL, "exit-policy/ipv6", &answer,
|
||||
&errmsg);
|
||||
tt_assert(rv == 0);
|
||||
tt_assert(answer != NULL);
|
||||
ipv6_len = strlen(answer);
|
||||
tt_assert(ipv6_len > 0);
|
||||
tor_free(answer);
|
||||
|
||||
rv = getinfo_helper_policies(NULL, "exit-policy/full", &answer,
|
||||
&errmsg);
|
||||
tt_assert(rv == 0);
|
||||
tt_assert(answer != NULL);
|
||||
tt_assert(strlen(answer) > 0);
|
||||
tt_assert(strlen(answer) == ipv4_len + ipv6_len + 1);
|
||||
tor_free(answer);
|
||||
|
||||
done:
|
||||
tor_free(answer);
|
||||
UNMOCK(get_options);
|
||||
UNMOCK(router_get_my_routerinfo);
|
||||
smartlist_free(mock_my_routerinfo.exit_policy);
|
||||
}
|
||||
|
||||
#undef DEFAULT_POLICY_STRING
|
||||
#undef TEST_IPV4_ADDR
|
||||
#undef TEST_IPV6_ADDR
|
||||
|
||||
struct testcase_t policy_tests[] = {
|
||||
{ "router_dump_exit_policy_to_string", test_dump_exit_policy_to_string, 0,
|
||||
NULL, NULL },
|
||||
{ "general", test_policies_general, 0, NULL, NULL },
|
||||
{ "getinfo_helper_policies", test_policies_getinfo_helper_policies, 0, NULL,
|
||||
NULL },
|
||||
{ "reject_exit_address", test_policies_reject_exit_address, 0, NULL, NULL },
|
||||
{ "reject_interface_address", test_policies_reject_interface_address, 0, NULL, NULL },
|
||||
{ "reject_port_address", test_policies_reject_port_address, 0, NULL, NULL },
|
||||
END_OF_TESTCASES
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user