diff options
Diffstat (limited to 'src/or/policies.c')
-rw-r--r-- | src/or/policies.c | 294 |
1 files changed, 199 insertions, 95 deletions
diff --git a/src/or/policies.c b/src/or/policies.c index 50fec3a773..f58bf329ad 100644 --- a/src/or/policies.c +++ b/src/or/policies.c @@ -103,7 +103,7 @@ policy_expand_private(smartlist_t **policy) if (tor_addr_parse_mask_ports(private_nets[i], 0, &newpolicy.addr, &newpolicy.maskbits, &port_min, &port_max)<0) { - tor_assert(0); + tor_assert_unreached(); } smartlist_add(tmp, addr_policy_get_canonical_entry(&newpolicy)); } @@ -274,28 +274,22 @@ parse_reachable_addresses(void) /* We ignore ReachableAddresses for relays */ if (!server_mode(options)) { - if ((reachable_or_addr_policy - && policy_is_reject_star(reachable_or_addr_policy, AF_UNSPEC)) - || (reachable_dir_addr_policy - && policy_is_reject_star(reachable_dir_addr_policy, AF_UNSPEC))) { + if (policy_is_reject_star(reachable_or_addr_policy, AF_UNSPEC, 0) + || policy_is_reject_star(reachable_dir_addr_policy, AF_UNSPEC,0)) { log_warn(LD_CONFIG, "Tor cannot connect to the Internet if " "ReachableAddresses, ReachableORAddresses, or " "ReachableDirAddresses reject all addresses. Please accept " "some addresses in these options."); } else if (options->ClientUseIPv4 == 1 - && ((reachable_or_addr_policy - && policy_is_reject_star(reachable_or_addr_policy, AF_INET)) - || (reachable_dir_addr_policy - && policy_is_reject_star(reachable_dir_addr_policy, AF_INET)))) { + && (policy_is_reject_star(reachable_or_addr_policy, AF_INET, 0) + || policy_is_reject_star(reachable_dir_addr_policy, AF_INET, 0))) { log_warn(LD_CONFIG, "You have set ClientUseIPv4 1, but " "ReachableAddresses, ReachableORAddresses, or " "ReachableDirAddresses reject all IPv4 addresses. " "Tor will not connect using IPv4."); } else if (fascist_firewall_use_ipv6(options) - && ((reachable_or_addr_policy - && policy_is_reject_star(reachable_or_addr_policy, AF_INET6)) - || (reachable_dir_addr_policy - && policy_is_reject_star(reachable_dir_addr_policy, AF_INET6)))) { + && (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 " "ReachableAddresses, ReachableORAddresses, or " @@ -860,6 +854,8 @@ fascist_firewall_choose_address_base(const tor_addr_t *ipv4_addr, ap->port = result->port; return 1; } else { + tor_addr_make_null(&ap->addr, AF_UNSPEC); + ap->port = 0; return 0; } } @@ -1084,8 +1080,8 @@ validate_addr_policies(const or_options_t *options, char **msg) const int exitrelay_setting_is_auto = options->ExitRelay == -1; const int policy_accepts_something = - ! (policy_is_reject_star(addr_policy, AF_INET) && - policy_is_reject_star(addr_policy, AF_INET6)); + ! (policy_is_reject_star(addr_policy, AF_INET, 1) && + policy_is_reject_star(addr_policy, AF_INET6, 1)); if (server_mode(options) && ! warned_about_exitrelay && @@ -1204,48 +1200,48 @@ policies_parse_from_options(const or_options_t *options) return ret; } -/** Compare two provided address policy items, and return -1, 0, or 1 +/** Compare two provided address policy items, and renturn -1, 0, or 1 * if the first is less than, equal to, or greater than the second. */ static int -cmp_single_addr_policy(addr_policy_t *a, addr_policy_t *b) +single_addr_policy_eq(const addr_policy_t *a, const addr_policy_t *b) { int r; - if ((r=((int)a->policy_type - (int)b->policy_type))) - return r; - if ((r=((int)a->is_private - (int)b->is_private))) - return r; +#define CMP_FIELD(field) do { \ + if (a->field != b->field) { \ + return 0; \ + } \ + } while (0) + CMP_FIELD(policy_type); + CMP_FIELD(is_private); /* 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))) - return r; - if ((r=((int)a->prt_min - (int)b->prt_min))) - return r; - if ((r=((int)a->prt_max - (int)b->prt_max))) - return r; - return 0; + return 0; + CMP_FIELD(maskbits); + CMP_FIELD(prt_min); + CMP_FIELD(prt_max); +#undef CMP_FIELD + return 1; } -/** Like cmp_single_addr_policy() above, but looks at the - * whole set of policies in each case. */ +/** As single_addr_policy_eq, but compare every element of two policies. + */ int -cmp_addr_policies(smartlist_t *a, smartlist_t *b) +addr_policies_eq(const smartlist_t *a, const smartlist_t *b) { - int r, i; + int i; int len_a = a ? smartlist_len(a) : 0; int len_b = b ? smartlist_len(b) : 0; - for (i = 0; i < len_a && i < len_b; ++i) { - if ((r = cmp_single_addr_policy(smartlist_get(a, i), smartlist_get(b, i)))) - return r; - } - if (i == len_a && i == len_b) + if (len_a != len_b) return 0; - if (i < len_a) - return -1; - else - return 1; + + for (i = 0; i < len_a; ++i) { + if (! single_addr_policy_eq(smartlist_get(a, i), smartlist_get(b, i))) + return 0; + } + + return 1; } /** Node in hashtable used to store address policy entries. */ @@ -1261,7 +1257,7 @@ static HT_HEAD(policy_map, policy_map_ent_t) policy_root = HT_INITIALIZER(); static inline int policy_eq(policy_map_ent_t *a, policy_map_ent_t *b) { - return cmp_single_addr_policy(a->policy, b->policy) == 0; + return single_addr_policy_eq(a->policy, b->policy); } /** Return a hashcode for <b>ent</b> */ @@ -1312,7 +1308,7 @@ addr_policy_get_canonical_entry(addr_policy_t *e) HT_INSERT(policy_map, &policy_root, found); } - tor_assert(!cmp_single_addr_policy(found->policy, e)); + tor_assert(single_addr_policy_eq(found->policy, e)); ++found->policy->refcnt; return found->policy; } @@ -1837,10 +1833,18 @@ policies_log_first_redundant_entry(const smartlist_t *policy) * * If <b>ipv6_exit</b> is false, prepend "reject *6:*" to the policy. * + * If <b>configured_addresses</b> contains addresses: + * - prepend entries that reject the addresses in this list. These may be the + * advertised relay addresses and/or the outbound bind addresses, + * depending on the ExitPolicyRejectPrivate and + * ExitPolicyRejectLocalInterfaces settings. * If <b>rejectprivate</b> is true: * - prepend "reject private:*" to the policy. - * - prepend entries that reject publicly routable addresses on this exit - * relay by calling policies_parse_exit_policy_reject_private + * If <b>reject_interface_addresses</b> is true: + * - prepend entries that reject publicly routable interface addresses on + * this exit relay by calling policies_parse_exit_policy_reject_private + * If <b>reject_configured_port_addresses</b> is true: + * - prepend entries that reject all configured port addresses * * If cfg doesn't end in an absolute accept or reject and if * <b>add_default_policy</b> is true, add the default exit @@ -1868,13 +1872,16 @@ policies_parse_exit_policy_internal(config_line_t *cfg, if (rejectprivate) { /* Reject IPv4 and IPv6 reserved private netblocks */ append_exit_policy_string(dest, "reject private:*"); - /* Reject IPv4 and IPv6 publicly routable addresses on this exit relay */ - policies_parse_exit_policy_reject_private( - dest, ipv6_exit, + } + + /* Consider rejecting IPv4 and IPv6 advertised relay addresses, outbound bind + * addresses, publicly routable addresses, and configured port 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; @@ -1902,8 +1909,14 @@ policies_parse_exit_policy_internal(config_line_t *cfg, * 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. + * - prepend entries that reject the advertised relay addresses in + * configured_addresses + * If <b>EXIT_POLICY_REJECT_LOCAL_INTERFACES</b> bit is set in <b>options</b>: * - prepend entries that reject publicly routable addresses on this exit * relay by calling policies_parse_exit_policy_internal + * - prepend entries that reject the outbound bind addresses in + * configured_addresses + * - prepend entries that reject all configured port addresses * * If <b>EXIT_POLICY_ADD_DEFAULT</b> bit is set in <b>options</b>, append * default exit policy entries to <b>result</b> smartlist. @@ -1916,12 +1929,14 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, int ipv6_enabled = (options & EXIT_POLICY_IPV6_ENABLED) ? 1 : 0; int reject_private = (options & EXIT_POLICY_REJECT_PRIVATE) ? 1 : 0; int add_default = (options & EXIT_POLICY_ADD_DEFAULT) ? 1 : 0; + int reject_local_interfaces = (options & + EXIT_POLICY_REJECT_LOCAL_INTERFACES) ? 1 : 0; return policies_parse_exit_policy_internal(cfg,dest,ipv6_enabled, reject_private, configured_addresses, - reject_private, - reject_private, + reject_local_interfaces, + reject_local_interfaces, add_default); } @@ -1987,6 +2002,7 @@ policies_copy_outbound_addresses_to_smartlist(smartlist_t *addr_list, * 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 <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 @@ -2030,11 +2046,20 @@ policies_parse_exit_policy_from_options(const or_options_t *or_options, parser_cfg |= EXIT_POLICY_ADD_DEFAULT; } + if (or_options->ExitPolicyRejectLocalInterfaces) { + parser_cfg |= EXIT_POLICY_REJECT_LOCAL_INTERFACES; + } + /* Copy the configured addresses into the tor_addr_t* list */ - policies_copy_ipv4h_to_smartlist(configured_addresses, local_address); - policies_copy_addr_to_smartlist(configured_addresses, ipv6_local_address); - policies_copy_outbound_addresses_to_smartlist(configured_addresses, - or_options); + if (or_options->ExitPolicyRejectPrivate) { + policies_copy_ipv4h_to_smartlist(configured_addresses, local_address); + policies_copy_addr_to_smartlist(configured_addresses, ipv6_local_address); + } + + if (or_options->ExitPolicyRejectLocalInterfaces) { + policies_copy_outbound_addresses_to_smartlist(configured_addresses, + or_options); + } rv = policies_parse_exit_policy(or_options->ExitPolicy, result, parser_cfg, configured_addresses); @@ -2090,8 +2115,10 @@ exit_policy_is_general_exit_helper(smartlist_t *policy, int port) if (subnet_status[i] != 0) continue; /* We already reject some part of this /8 */ tor_addr_from_ipv4h(&addr, i<<24); - if (tor_addr_is_internal(&addr, 0)) + if (tor_addr_is_internal(&addr, 0) && + !get_options()->DirAllowPrivateAddresses) { continue; /* Local or non-routable addresses */ + } if (p->policy_type == ADDR_POLICY_ACCEPT) { if (p->maskbits > 8) continue; /* Narrower than a /8. */ @@ -2125,13 +2152,16 @@ exit_policy_is_general_exit(smartlist_t *policy) } /** Return false if <b>policy</b> might permit access to some addr:port; - * otherwise if we are certain it rejects everything, return true. */ + * otherwise if we are certain it rejects everything, return true. If no + * part of <b>policy</b> matches, return <b>default_reject</b>. + * NULL policies are allowed, and treated as empty. */ int -policy_is_reject_star(const smartlist_t *policy, sa_family_t family) +policy_is_reject_star(const smartlist_t *policy, sa_family_t family, + int default_reject) { - if (!policy) /*XXXX disallow NULL policies? */ - return 1; - SMARTLIST_FOREACH_BEGIN(policy, addr_policy_t *, p) { + if (!policy) + return default_reject; + SMARTLIST_FOREACH_BEGIN(policy, const addr_policy_t *, p) { if (p->policy_type == ADDR_POLICY_ACCEPT && (tor_addr_family(&p->addr) == family || tor_addr_family(&p->addr) == AF_UNSPEC)) { @@ -2144,7 +2174,7 @@ policy_is_reject_star(const smartlist_t *policy, sa_family_t family) return 1; } } SMARTLIST_FOREACH_END(p); - return 1; + return default_reject; } /** Write a single address policy to the buf_len byte buffer at buf. Return @@ -2271,7 +2301,26 @@ policy_summary_item_split(policy_summary_item_t* old, uint16_t new_starts) * my immortal soul, he can clean it up himself. */ #define AT(x) ((policy_summary_item_t*)smartlist_get(summary, x)) -#define REJECT_CUTOFF_COUNT (1<<25) +#define IPV4_BITS (32) +/* Every IPv4 address is counted as one rejection */ +#define REJECT_CUTOFF_SCALE_IPV4 (0) +/* Ports are rejected in an IPv4 summary if they are rejected in more than two + * IPv4 /8 address blocks */ +#define REJECT_CUTOFF_COUNT_IPV4 (U64_LITERAL(1) << \ + (IPV4_BITS - REJECT_CUTOFF_SCALE_IPV4 - 7)) + +#define IPV6_BITS (128) +/* IPv6 /64s are counted as one rejection, anything smaller is ignored */ +#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 + * some scattered smaller blocks) have been allocated to the RIRs. + * Network providers are typically allocated one or more IPv6 /32s. + */ +#define REJECT_CUTOFF_COUNT_IPV6 (U64_LITERAL(1) << \ + (IPV6_BITS - REJECT_CUTOFF_SCALE_IPV6 - 16)) + /** Split an exit policy summary so that prt_min and prt_max * fall at exactly the start and end of an item respectively. */ @@ -2304,53 +2353,102 @@ policy_summary_split(smartlist_t *summary, return start_at_index; } -/** Mark port ranges as accepted if they are below the reject_count */ +/** Mark port ranges as accepted if they are below the reject_count for family + */ static void policy_summary_accept(smartlist_t *summary, - uint16_t prt_min, uint16_t prt_max) + uint16_t prt_min, uint16_t prt_max, + sa_family_t family) { + tor_assert_nonfatal_once(family == AF_INET || family == AF_INET6); + uint64_t family_reject_count = ((family == AF_INET) ? + REJECT_CUTOFF_COUNT_IPV4 : + REJECT_CUTOFF_COUNT_IPV6); + int i = policy_summary_split(summary, prt_min, prt_max); while (i < smartlist_len(summary) && AT(i)->prt_max <= prt_max) { if (!AT(i)->accepted && - AT(i)->reject_count <= REJECT_CUTOFF_COUNT) + AT(i)->reject_count <= family_reject_count) AT(i)->accepted = 1; i++; } tor_assert(i < smartlist_len(summary) || prt_max==65535); } -/** Count the number of addresses in a network with prefixlen maskbits - * against the given portrange. */ +/** Count the number of addresses in a network in family with prefixlen + * maskbits against the given portrange. */ static void policy_summary_reject(smartlist_t *summary, maskbits_t maskbits, - uint16_t prt_min, uint16_t prt_max) + uint16_t prt_min, uint16_t prt_max, + sa_family_t family) { + tor_assert_nonfatal_once(family == AF_INET || family == AF_INET6); + int i = policy_summary_split(summary, prt_min, prt_max); - /* XXX: ipv4 specific */ - uint64_t count = (U64_LITERAL(1) << (32-maskbits)); + + /* The length of a single address mask */ + int addrbits = (family == AF_INET) ? IPV4_BITS : IPV6_BITS; + tor_assert_nonfatal_once(addrbits >= maskbits); + + /* We divide IPv6 address counts by (1 << scale) to keep them in a uint64_t + */ + int scale = ((family == AF_INET) ? + REJECT_CUTOFF_SCALE_IPV4 : + REJECT_CUTOFF_SCALE_IPV6); + + tor_assert_nonfatal_once(addrbits >= scale); + if (maskbits > (addrbits - scale)) { + tor_assert_nonfatal_once(family == AF_INET6); + /* The address range is so small, we'd need billions of them to reach the + * rejection limit. So we ignore this range in the reject count. */ + return; + } + + uint64_t count = 0; + if (addrbits - scale - maskbits >= 64) { + tor_assert_nonfatal_once(family == AF_INET6); + /* The address range is so large, it's an automatic rejection for all ports + * in the range. */ + count = UINT64_MAX; + } else { + count = (U64_LITERAL(1) << (addrbits - scale - maskbits)); + } + tor_assert_nonfatal_once(count > 0); while (i < smartlist_len(summary) && AT(i)->prt_max <= prt_max) { - AT(i)->reject_count += count; + if (AT(i)->reject_count <= UINT64_MAX - count) { + AT(i)->reject_count += count; + } else { + /* IPv4 would require a 4-billion address redundant policy to get here, + * but IPv6 just needs to have ::/0 */ + if (family == AF_INET) { + tor_assert_nonfatal_unreached_once(); + } + /* If we do get here, use saturating arithmetic */ + AT(i)->reject_count = UINT64_MAX; + } i++; } tor_assert(i < smartlist_len(summary) || prt_max==65535); } /** Add a single exit policy item to our summary: - * If it is an accept ignore it unless it is for all IP addresses - * ("*"), i.e. it's prefixlen/maskbits is 0, else call + * + * If it is an accept, ignore it unless it is for all IP addresses + * ("*", i.e. its prefixlen/maskbits is 0). Otherwise call * policy_summary_accept(). - * If it's a reject ignore it if it is about one of the private - * networks, else call policy_summary_reject(). + * + * If it is a reject, ignore it if it is about one of the private + * networks. Otherwise call policy_summary_reject(). */ static void policy_summary_add_item(smartlist_t *summary, addr_policy_t *p) { if (p->policy_type == ADDR_POLICY_ACCEPT) { if (p->maskbits == 0) { - policy_summary_accept(summary, p->prt_min, p->prt_max); + policy_summary_accept(summary, p->prt_min, p->prt_max, p->addr.family); } } else if (p->policy_type == ADDR_POLICY_REJECT) { @@ -2371,7 +2469,8 @@ policy_summary_add_item(smartlist_t *summary, addr_policy_t *p) } if (!is_private) { - policy_summary_reject(summary, p->maskbits, p->prt_min, p->prt_max); + policy_summary_reject(summary, p->maskbits, p->prt_min, p->prt_max, + p->addr.family); } } else tor_assert(0); @@ -2405,7 +2504,6 @@ policy_summarize(smartlist_t *policy, sa_family_t family) } if (f != family) continue; - /* XXXX-ipv6 More family work is needed */ policy_summary_add_item(summary, p); } SMARTLIST_FOREACH_END(p); @@ -2594,8 +2692,7 @@ parse_short_policy(const char *summary) return result; } -/** Write <b>policy</b> back out into a string. Used only for unit tests - * currently. */ +/** Write <b>policy</b> back out into a string. */ char * write_short_policy(const short_policy_t *policy) { @@ -2638,7 +2735,7 @@ compare_tor_addr_to_short_policy(const tor_addr_t *addr, uint16_t port, { int i; int found_match = 0; - int accept; + int accept_; tor_assert(port != 0); @@ -2658,9 +2755,9 @@ compare_tor_addr_to_short_policy(const tor_addr_t *addr, uint16_t port, } if (found_match) - accept = policy->is_accept; + accept_ = policy->is_accept; else - accept = ! policy->is_accept; + accept_ = ! policy->is_accept; /* ???? are these right? -NM */ /* We should be sure not to return ADDR_POLICY_ACCEPTED in the accept @@ -2673,7 +2770,7 @@ compare_tor_addr_to_short_policy(const tor_addr_t *addr, uint16_t port, * * Once microdescriptors can handle addresses in special cases (e.g. if * we ever solve ticket 1774), we can provide certainty here. -RD */ - if (accept) + if (accept_) return ADDR_POLICY_PROBABLY_ACCEPTED; else return ADDR_POLICY_REJECTED; @@ -2814,7 +2911,8 @@ getinfo_helper_policies(control_connection_t *conn, return -1; } - if (!options->ExitPolicyRejectPrivate) { + if (!options->ExitPolicyRejectPrivate && + !options->ExitPolicyRejectLocalInterfaces) { *answer = tor_strdup(""); return 0; } @@ -2823,16 +2921,22 @@ getinfo_helper_policies(control_connection_t *conn, smartlist_t *configured_addresses = smartlist_new(); /* Copy the configured addresses into the tor_addr_t* list */ - policies_copy_ipv4h_to_smartlist(configured_addresses, me->addr); - policies_copy_addr_to_smartlist(configured_addresses, &me->ipv6_addr); - policies_copy_outbound_addresses_to_smartlist(configured_addresses, - options); + if (options->ExitPolicyRejectPrivate) { + policies_copy_ipv4h_to_smartlist(configured_addresses, me->addr); + policies_copy_addr_to_smartlist(configured_addresses, &me->ipv6_addr); + } + + if (options->ExitPolicyRejectLocalInterfaces) { + policies_copy_outbound_addresses_to_smartlist(configured_addresses, + options); + } policies_parse_exit_policy_reject_private( - &private_policy_list, - options->IPv6Exit, - configured_addresses, - 1, 1); + &private_policy_list, + options->IPv6Exit, + configured_addresses, + options->ExitPolicyRejectLocalInterfaces, + options->ExitPolicyRejectLocalInterfaces); *answer = policy_dump_to_string(private_policy_list, 1, 1); addr_policy_list_free(private_policy_list); |