aboutsummaryrefslogtreecommitdiff
path: root/src/or/policies.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/policies.c')
-rw-r--r--src/or/policies.c191
1 files changed, 142 insertions, 49 deletions
diff --git a/src/or/policies.c b/src/or/policies.c
index f58bf329ad..f718ded326 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -1,18 +1,27 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file policies.c
* \brief Code to parse and use address policies and exit policies.
+ *
+ * We have two key kinds of address policy: full and compressed. A full
+ * policy is an array of accept/reject patterns, to be applied in order.
+ * A short policy is simply a list of ports. This module handles both
+ * kinds, including generic functions to apply them to addresses, and
+ * also including code to manage the global policies that we apply to
+ * incoming and outgoing connections.
**/
#define POLICIES_PRIVATE
#include "or.h"
+#include "bridges.h"
#include "config.h"
#include "dirserv.h"
+#include "microdesc.h"
#include "networkstatus.h"
#include "nodelist.h"
#include "policies.h"
@@ -73,7 +82,8 @@ static int policies_parse_exit_policy_internal(
const smartlist_t *configured_addresses,
int reject_interface_addresses,
int reject_configured_port_addresses,
- int add_default_policy);
+ int add_default_policy,
+ int add_reduced_policy);
/** Replace all "private" entries in *<b>policy</b> with their expanded
* equivalents. */
@@ -290,8 +300,8 @@ parse_reachable_addresses(void)
} else if (fascist_firewall_use_ipv6(options)
&& (policy_is_reject_star(reachable_or_addr_policy, AF_INET6, 0)
|| policy_is_reject_star(reachable_dir_addr_policy, AF_INET6, 0))) {
- log_warn(LD_CONFIG, "You have configured tor to use IPv6 "
- "(ClientUseIPv6 1 or UseBridges 1), but "
+ log_warn(LD_CONFIG, "You have configured tor to use or prefer IPv6 "
+ "(or UseBridges 1), but "
"ReachableAddresses, ReachableORAddresses, or "
"ReachableDirAddresses reject all IPv6 addresses. "
"Tor will not connect using IPv6.");
@@ -309,10 +319,8 @@ firewall_is_fascist_impl(void)
const or_options_t *options = get_options();
/* Assume every non-bridge relay has an IPv4 address.
* Clients which use bridges may only know the IPv6 address of their
- * bridge. */
- return (options->ClientUseIPv4 == 0
- || (!fascist_firewall_use_ipv6(options)
- && options->UseBridges == 1));
+ * bridge, but they will connect regardless of the ClientUseIPv6 setting. */
+ return options->ClientUseIPv4 == 0;
}
/** Return true iff the firewall options, including ClientUseIPv4 0 and
@@ -419,6 +427,9 @@ fascist_firewall_allows_address(const tor_addr_t *addr,
}
/** Is this client configured to use IPv6?
+ * Returns true if the client might use IPv6 for some of its connections
+ * (including dual-stack and IPv6-only clients), and false if it will never
+ * use IPv6 for any connections.
* Use node_ipv6_or/dir_preferred() when checking a specific node and OR/Dir
* port: it supports bridge client per-node IPv6 preferences.
*/
@@ -426,9 +437,11 @@ int
fascist_firewall_use_ipv6(const or_options_t *options)
{
/* Clients use IPv6 if it's set, or they use bridges, or they don't use
- * IPv4 */
- return (options->ClientUseIPv6 == 1 || options->UseBridges == 1
- || options->ClientUseIPv4 == 0);
+ * IPv4, or they prefer it.
+ * ClientPreferIPv6DirPort is deprecated, but check it anyway. */
+ return (options->ClientUseIPv6 == 1 || options->ClientUseIPv4 == 0 ||
+ options->ClientPreferIPv6ORPort == 1 ||
+ options->ClientPreferIPv6DirPort == 1 || options->UseBridges == 1);
}
/** Do we prefer to connect to IPv6, ignoring ClientPreferIPv6ORPort and
@@ -883,6 +896,49 @@ fascist_firewall_choose_address_ipv4h(uint32_t ipv4h_addr,
pref_ipv6, ap);
}
+/* Some microdescriptor consensus methods have no IPv6 addresses in rs: they
+ * are in the microdescriptors. For these consensus methods, we can't rely on
+ * the node's IPv6 address until its microdescriptor is available (when using
+ * microdescs).
+ * But for bridges, rewrite_node_address_for_bridge() updates node->ri with
+ * the configured address, so we can trust bridge addresses.
+ * (Bridges could gain an IPv6 address if their microdescriptor arrives, but
+ * this will never be their preferred address: that is in the config.)
+ * Returns true if the node needs a microdescriptor for its IPv6 address, and
+ * false if the addresses in the node are already up-to-date.
+ */
+static int
+node_awaiting_ipv6(const or_options_t* options, const node_t *node)
+{
+ tor_assert(node);
+
+ /* There's no point waiting for an IPv6 address if we'd never use it */
+ if (!fascist_firewall_use_ipv6(options)) {
+ return 0;
+ }
+
+ /* If the node has an IPv6 address, we're not waiting */
+ if (node_has_ipv6_addr(node)) {
+ return 0;
+ }
+
+ /* If the current consensus method and flavour has IPv6 addresses, we're not
+ * waiting */
+ if (networkstatus_consensus_has_ipv6(options)) {
+ return 0;
+ }
+
+ /* Bridge clients never use the address from a bridge's md, so there's no
+ * need to wait for it. */
+ if (node_is_a_configured_bridge(node)) {
+ return 0;
+ }
+
+ /* We are waiting if we_use_microdescriptors_for_circuits() and we have no
+ * md. */
+ return (!node->md && we_use_microdescriptors_for_circuits(options));
+}
+
/** Like fascist_firewall_choose_address_base(), but takes <b>rs</b>.
* Consults the corresponding node, then falls back to rs if node is NULL.
* This should only happen when there's no valid consensus, and rs doesn't
@@ -899,15 +955,15 @@ fascist_firewall_choose_address_rs(const routerstatus_t *rs,
tor_assert(ap);
+ const or_options_t *options = get_options();
const node_t *node = node_get_by_id(rs->identity_digest);
- if (node) {
+ if (node && !node_awaiting_ipv6(options, node)) {
return fascist_firewall_choose_address_node(node, fw_connection, pref_only,
ap);
} else {
/* There's no node-specific IPv6 preference, so use the generic IPv6
* preference instead. */
- const or_options_t *options = get_options();
int pref_ipv6 = (fw_connection == FIREWALL_OR_CONNECTION
? fascist_firewall_prefer_ipv6_orport(options)
: fascist_firewall_prefer_ipv6_dirport(options));
@@ -941,6 +997,18 @@ fascist_firewall_choose_address_node(const node_t *node,
node_assert_ok(node);
+ /* Calling fascist_firewall_choose_address_node() when the node is missing
+ * IPv6 information breaks IPv6-only clients.
+ * If the node is a hard-coded fallback directory or authority, call
+ * fascist_firewall_choose_address_rs() on the fake (hard-coded) routerstatus
+ * for the node.
+ * If it is not hard-coded, check that the node has a microdescriptor, full
+ * descriptor (routerinfo), or is one of our configured bridges before
+ * calling this function. */
+ if (BUG(node_awaiting_ipv6(get_options(), node))) {
+ return 0;
+ }
+
const int pref_ipv6_node = (fw_connection == FIREWALL_OR_CONNECTION
? node_ipv6_or_preferred(node)
: node_ipv6_dir_preferred(node));
@@ -1096,7 +1164,7 @@ validate_addr_policies(const or_options_t *options, char **msg)
"to 1 to disable this warning, and for forward compatibility.",
options->ExitPolicy == NULL ?
" with the default exit policy" : "");
- if (options->ExitPolicy == NULL) {
+ if (options->ExitPolicy == NULL && options->ReducedExitPolicy == 0) {
log_warn(LD_CONFIG,
"In a future version of Tor, ExitRelay 0 may become the "
"default when no ExitPolicy is given.");
@@ -1743,14 +1811,14 @@ policies_parse_exit_policy_reject_private(
/* 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);
+ interface_address6_list_free(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);
+ interface_address6_list_free(public_addresses);
}
}
@@ -1829,6 +1897,24 @@ policies_log_first_redundant_entry(const smartlist_t *policy)
"reject *:563,reject *:1214,reject *:4661-4666," \
"reject *:6346-6429,reject *:6699,reject *:6881-6999,accept *:*"
+#define REDUCED_EXIT_POLICY \
+ "accept *:20-23,accept *:43,accept *:53,accept *:79-81,accept *:88," \
+ "accept *:110,accept *:143,accept *:194,accept *:220,accept *:389," \
+ "accept *:443,accept *:464,accept *:465,accept *:531,accept *:543-544," \
+ "accept *:554,accept *:563,accept *:587,accept *:636,accept *:706," \
+ "accept *:749,accept *:873,accept *:902-904,accept *:981,accept *:989-995," \
+ "accept *:1194,accept *:1220,accept *:1293,accept *:1500,accept *:1533," \
+ "accept *:1677,accept *:1723,accept *:1755,accept *:1863," \
+ "accept *:2082-2083,accept *:2086-2087,accept *:2095-2096," \
+ "accept *:2102-2104,accept *:3128,accept *:3389,accept *:3690," \
+ "accept *:4321,accept *:4643,accept *:5050,accept *:5190," \
+ "accept *:5222-5223,accept *:5228,accept *:5900,accept *:6660-6669," \
+ "accept *:6679,accept *:6697,accept *:8000,accept *:8008,accept *:8074," \
+ "accept *:8080,accept *:8082,accept *:8087-8088,accept *:8232-8233," \
+ "accept *:8332-8333,accept *:8443,accept *:8888,accept *:9418," \
+ "accept *:9999,accept *:10000,accept *:11371,accept *:19294," \
+ "accept *:19638,accept *:50002,accept *:64738,reject *:*"
+
/** Parse the exit policy <b>cfg</b> into the linked list *<b>dest</b>.
*
* If <b>ipv6_exit</b> is false, prepend "reject *6:*" to the policy.
@@ -1864,7 +1950,8 @@ policies_parse_exit_policy_internal(config_line_t *cfg,
const smartlist_t *configured_addresses,
int reject_interface_addresses,
int reject_configured_port_addresses,
- int add_default_policy)
+ int add_default_policy,
+ int add_reduced_policy)
{
if (!ipv6_exit) {
append_exit_policy_string(dest, "reject *6:*");
@@ -1890,7 +1977,9 @@ policies_parse_exit_policy_internal(config_line_t *cfg,
* effect, and are most likely an error. */
policies_log_first_redundant_entry(*dest);
- if (add_default_policy) {
+ if (add_reduced_policy) {
+ append_exit_policy_string(dest, REDUCED_EXIT_POLICY);
+ } else if (add_default_policy) {
append_exit_policy_string(dest, DEFAULT_EXIT_POLICY);
} else {
append_exit_policy_string(dest, "reject *4:*");
@@ -1931,13 +2020,15 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
int add_default = (options & EXIT_POLICY_ADD_DEFAULT) ? 1 : 0;
int reject_local_interfaces = (options &
EXIT_POLICY_REJECT_LOCAL_INTERFACES) ? 1 : 0;
+ int add_reduced = (options & EXIT_POLICY_ADD_REDUCED) ? 1 : 0;
return policies_parse_exit_policy_internal(cfg,dest,ipv6_enabled,
reject_private,
configured_addresses,
reject_local_interfaces,
reject_local_interfaces,
- add_default);
+ add_default,
+ add_reduced);
}
/** Helper function that adds a copy of addr to a smartlist as long as it is
@@ -1971,10 +2062,10 @@ policies_copy_ipv4h_to_smartlist(smartlist_t *addr_list, uint32_t ipv4h_addr)
}
}
-/** Helper function that adds copies of
- * or_options->OutboundBindAddressIPv[4|6]_ to a smartlist as tor_addr_t *, as
- * long as or_options is non-NULL, and the addresses are not
- * tor_addr_is_null(), by passing them to policies_add_addr_to_smartlist.
+/** Helper function that adds copies of or_options->OutboundBindAddresses
+ * to a smartlist as tor_addr_t *, as long as or_options is non-NULL, and
+ * the addresses are not tor_addr_is_null(), by passing them to
+ * policies_add_addr_to_smartlist.
*
* The caller is responsible for freeing all the tor_addr_t* in the smartlist.
*/
@@ -1983,10 +2074,14 @@ policies_copy_outbound_addresses_to_smartlist(smartlist_t *addr_list,
const or_options_t *or_options)
{
if (or_options) {
- policies_copy_addr_to_smartlist(addr_list,
- &or_options->OutboundBindAddressIPv4_);
- policies_copy_addr_to_smartlist(addr_list,
- &or_options->OutboundBindAddressIPv6_);
+ for (int i=0;i<OUTBOUND_ADDR_MAX;i++) {
+ for (int j=0;j<2;j++) {
+ if (!tor_addr_is_null(&or_options->OutboundBindAddresses[i][j])) {
+ policies_copy_addr_to_smartlist(addr_list,
+ &or_options->OutboundBindAddresses[i][j]);
+ }
+ }
+ }
}
}
@@ -2003,10 +2098,10 @@ policies_copy_outbound_addresses_to_smartlist(smartlist_t *addr_list,
* - if ipv6_local_address is non-NULL, and not the null tor_addr_t, add it
* to the list of configured addresses.
* If <b>or_options->ExitPolicyRejectLocalInterfaces</b> is true:
- * - 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 or_options->OutboundBindAddresses[][0] (=IPv4) is not the null
+ * tor_addr_t, add it to the list of configured addresses.
+ * - if or_options->OutboundBindAddresses[][1] (=IPv6) 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.
@@ -2043,7 +2138,10 @@ policies_parse_exit_policy_from_options(const or_options_t *or_options,
}
if (!or_options->BridgeRelay) {
- parser_cfg |= EXIT_POLICY_ADD_DEFAULT;
+ if (or_options->ReducedExitPolicy)
+ parser_cfg |= EXIT_POLICY_ADD_REDUCED;
+ else
+ parser_cfg |= EXIT_POLICY_ADD_DEFAULT;
}
if (or_options->ExitPolicyRejectLocalInterfaces) {
@@ -2134,21 +2232,16 @@ exit_policy_is_general_exit_helper(smartlist_t *policy, int port)
}
/** Return true iff <b>ri</b> is "useful as an exit node", meaning
- * it allows exit to at least one /8 address space for at least
- * two of ports 80, 443, and 6667. */
+ * it allows exit to at least one /8 address space for each of ports 80
+ * and 443. */
int
exit_policy_is_general_exit(smartlist_t *policy)
{
- static const int ports[] = { 80, 443, 6667 };
- int n_allowed = 0;
- int i;
if (!policy) /*XXXX disallow NULL policies? */
return 0;
- for (i = 0; i < 3; ++i) {
- n_allowed += exit_policy_is_general_exit_helper(policy, ports[i]);
- }
- return n_allowed >= 2;
+ return (exit_policy_is_general_exit_helper(policy, 80) &&
+ exit_policy_is_general_exit_helper(policy, 443));
}
/** Return false if <b>policy</b> might permit access to some addr:port;
@@ -2314,7 +2407,7 @@ policy_summary_item_split(policy_summary_item_t* old, uint16_t new_starts)
#define REJECT_CUTOFF_SCALE_IPV6 (64)
/* Ports are rejected in an IPv6 summary if they are rejected in more than one
* IPv6 /16 address block.
- * This is rougly equivalent to the IPv4 cutoff, as only five IPv6 /12s (and
+ * This is roughly equivalent to the IPv4 cutoff, as only five IPv6 /12s (and
* some scattered smaller blocks) have been allocated to the RIRs.
* Network providers are typically allocated one or more IPv6 /32s.
*/
@@ -2528,9 +2621,9 @@ policy_summarize(smartlist_t *policy, sa_family_t family)
tor_snprintf(buf, sizeof(buf), "%d-%d", start_prt, AT(i)->prt_max);
if (AT(i)->accepted)
- smartlist_add(accepts, tor_strdup(buf));
+ smartlist_add_strdup(accepts, buf);
else
- smartlist_add(rejects, tor_strdup(buf));
+ smartlist_add_strdup(rejects, buf);
if (last)
break;
@@ -2679,7 +2772,7 @@ parse_short_policy(const char *summary)
}
{
- size_t size = STRUCT_OFFSET(short_policy_t, entries) +
+ size_t size = offsetof(short_policy_t, entries) +
sizeof(short_policy_entry_t)*(n_entries);
result = tor_malloc_zero(size);
@@ -2710,7 +2803,7 @@ write_short_policy(const short_policy_t *policy)
smartlist_add_asprintf(sl, "%d-%d", e->min_port, e->max_port);
}
if (i < policy->n_entries-1)
- smartlist_add(sl, tor_strdup(","));
+ smartlist_add_strdup(sl, ",");
}
answer = smartlist_join_strings(sl, "", 0, NULL);
SMARTLIST_FOREACH(sl, char *, a, tor_free(a));
@@ -2720,7 +2813,7 @@ write_short_policy(const short_policy_t *policy)
/** Release all storage held in <b>policy</b>. */
void
-short_policy_free(short_policy_t *policy)
+short_policy_free_(short_policy_t *policy)
{
tor_free(policy);
}
@@ -2970,7 +3063,7 @@ getinfo_helper_policies(control_connection_t *conn,
/** Release all storage held by <b>p</b>. */
void
-addr_policy_list_free(smartlist_t *lst)
+addr_policy_list_free_(smartlist_t *lst)
{
if (!lst)
return;
@@ -2980,7 +3073,7 @@ addr_policy_list_free(smartlist_t *lst)
/** Release all storage held by <b>p</b>. */
void
-addr_policy_free(addr_policy_t *p)
+addr_policy_free_(addr_policy_t *p)
{
if (!p)
return;