summaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
Diffstat (limited to 'src/or')
-rw-r--r--src/or/control.c6
-rw-r--r--src/or/policies.c307
-rw-r--r--src/or/policies.h15
3 files changed, 204 insertions, 124 deletions
diff --git a/src/or/control.c b/src/or/control.c
index 7d72342293..7e65611a88 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -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"),
diff --git a/src/or/policies.c b/src/or/policies.c
index 0e7b3bda2e..f4cde43ae4 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -63,17 +63,14 @@ static const char *private_nets[] = {
};
static int policies_parse_exit_policy_internal(
- config_line_t *cfg,
- smartlist_t **dest,
- int ipv6_exit,
- int rejectprivate,
- uint32_t local_address,
- const tor_addr_t *ipv6_local_address,
- const tor_addr_t *ipv4_outbound_address,
- const tor_addr_t *ipv6_outbound_address,
- int reject_interface_addresses,
- int reject_configured_port_addresses,
- int add_default_policy);
+ 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. */
@@ -868,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;
@@ -885,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;
@@ -902,17 +902,68 @@ addr_policy_append_reject_addr(smartlist_t **dest, const tor_addr_t *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>. */
static void
exit_policy_remove_redundancies(smartlist_t *dest)
@@ -997,21 +1048,12 @@ exit_policy_remove_redundancies(smartlist_t *dest)
}
}
-/* 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);
-}
-
/** 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 local_address is non-zero, treat it as a host-order IPv4 address,
- * and add an entry that rejects it as a destination.
- * - if ipv6_local_address, ipv4_outbound_address, or ipv6_outbound_address
- * are non-NULL, add entries that reject them as destinations.
+ * - 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
@@ -1027,60 +1069,16 @@ void
policies_parse_exit_policy_reject_private(
smartlist_t **dest,
int ipv6_exit,
- uint32_t local_address,
- const tor_addr_t *ipv6_local_address,
- const tor_addr_t *ipv4_outbound_address,
- const tor_addr_t *ipv6_outbound_address,
+ const smartlist_t *configured_addresses,
int reject_interface_addresses,
int reject_configured_port_addresses)
{
tor_assert(dest);
- /* Reject our local IPv4 address */
- if (local_address) {
- tor_addr_t v4_local;
- tor_addr_from_ipv4h(&v4_local, local_address);
- if (tor_addr_is_public_for_reject(&v4_local)) {
- addr_policy_append_reject_addr(dest, &v4_local);
- log_info(LD_CONFIG, "Adding a reject ExitPolicy 'reject %s:*' for our "
- "published IPv4 address", fmt_addr32(local_address));
- }
- }
-
- /* Reject the outbound IPv4 connection address */
- if (ipv4_outbound_address
- && tor_addr_is_public_for_reject(ipv4_outbound_address)) {
- addr_policy_append_reject_addr(dest, ipv4_outbound_address);
- log_info(LD_CONFIG, "Adding a reject ExitPolicy 'reject %s:*' for "
- "our outbound IPv4 connection address",
- fmt_addr(ipv4_outbound_address));
- }
-
- /* If we're not an IPv6 exit, all IPv6 addresses have already been rejected
- * by policies_parse_exit_policy_internal */
- if (ipv6_exit) {
-
- /* Reject our local IPv6 address */
- if (ipv6_local_address != NULL
- && tor_addr_is_public_for_reject(ipv6_local_address)) {
- 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 {
- addr_policy_append_reject_addr(dest, ipv6_local_address);
- log_info(LD_CONFIG, "Adding a reject ExitPolicy 'reject [%s]:*' for "
- "our published IPv6 address", fmt_addr(ipv6_local_address));
- }
- }
-
- /* Reject the outbound IPv6 connection address */
- if (ipv6_outbound_address
- && tor_addr_is_public_for_reject(ipv6_outbound_address)) {
- addr_policy_append_reject_addr(dest, ipv6_outbound_address);
- log_info(LD_CONFIG, "Adding a reject ExitPolicy 'reject [%s]:*' for "
- "our outbound IPv6 connection address",
- fmt_addr(ipv6_outbound_address));
- }
+ /* 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. */
@@ -1089,14 +1087,9 @@ policies_parse_exit_policy_reject_private(
SMARTLIST_FOREACH_BEGIN(port_addrs, port_cfg_t *, port) {
- /* Only reject IP addresses which are public */
- if (!port->is_unix_addr && tor_addr_is_public_for_reject(&port->addr)) {
-
- /* Reject IPv4 addresses. If we are an IPv6 exit, also reject IPv6
- * addresses */
- if (tor_addr_is_v4(&port->addr) || ipv6_exit) {
- addr_policy_append_reject_addr(dest, &port->addr);
- }
+ /* 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);
}
@@ -1107,13 +1100,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(dest, public_addresses);
+ 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(dest, public_addresses);
+ addr_policy_append_reject_addr_list_filter(dest, public_addresses, 0, 1);
free_interface_address6_list(public_addresses);
}
}
@@ -1149,13 +1143,11 @@ policies_parse_exit_policy_reject_private(
* 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,
- const tor_addr_t *ipv6_local_address,
- const tor_addr_t *ipv4_outbound_address,
- const tor_addr_t *ipv6_outbound_address,
+ const smartlist_t *configured_addresses,
int reject_interface_addresses,
int reject_configured_port_addresses,
int add_default_policy)
@@ -1168,10 +1160,8 @@ policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest,
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, local_address,
- ipv6_local_address,
- ipv4_outbound_address,
- ipv6_outbound_address,
+ dest, ipv6_exit,
+ configured_addresses,
reject_interface_addresses,
reject_configured_port_addresses);
}
@@ -1256,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.
@@ -1269,10 +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,
- const tor_addr_t *ipv6_local_address,
- const tor_addr_t *ipv4_outbound_address,
- const tor_addr_t *ipv6_outbound_address)
+ 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;
@@ -1280,15 +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,
- ipv4_outbound_address,
- ipv6_outbound_address,
+ 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
@@ -1298,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.
@@ -1317,13 +1338,17 @@ policies_parse_exit_policy_from_options(const or_options_t *or_options,
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;
}
@@ -1336,11 +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,
- &or_options->OutboundBindAddressIPv4_,
- &or_options->OutboundBindAddressIPv6_);
+ /* 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
@@ -2085,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();
diff --git a/src/or/policies.h b/src/or/policies.h
index d7cc5a30ba..72e62c7de0 100644
--- a/src/or/policies.h
+++ b/src/or/policies.h
@@ -44,7 +44,6 @@ 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);
@@ -55,17 +54,11 @@ int policies_parse_exit_policy_from_options(
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,
- const tor_addr_t *ipv6_local_address,
- const tor_addr_t *ipv4_outbound_address,
- const tor_addr_t *ipv6_outbound_address);
+ const smartlist_t *configured_addresses);
void policies_parse_exit_policy_reject_private(
smartlist_t **dest,
int ipv6_exit,
- uint32_t local_address,
- const tor_addr_t *ipv6_local_address,
- const tor_addr_t *ipv4_outbound_address,
- const tor_addr_t *ipv6_outbound_address,
+ const smartlist_t *configured_addresses,
int reject_interface_addresses,
int reject_configured_port_addresses);
void policies_exit_policy_append_reject_star(smartlist_t **dest);
@@ -99,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