diff options
author | teor (Tim Wilson-Brown) <teor2345@gmail.com> | 2015-11-16 15:54:57 +1100 |
---|---|---|
committer | teor (Tim Wilson-Brown) <teor2345@gmail.com> | 2015-11-20 10:39:13 +1100 |
commit | 66fac9fbadae529349f00172760688cf3caeb64d (patch) | |
tree | 64f278e70503f13a0cdf8c7cdf8d9afda7063343 /src/or | |
parent | e726ad466445e600b006295a8d2315643d1680da (diff) | |
download | tor-66fac9fbadae529349f00172760688cf3caeb64d.tar.gz tor-66fac9fbadae529349f00172760688cf3caeb64d.zip |
Block OutboundBindAddressIPv[4|6]_ and configured ports on exit relays
Modify policies_parse_exit_policy_reject_private so it also blocks
the addresses configured for OutboundBindAddressIPv4_ and
OutboundBindAddressIPv6_, and any publicly routable port addresses
on exit relays.
Add and update unit tests for these functions.
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/config.c | 9 | ||||
-rw-r--r-- | src/or/config.h | 4 | ||||
-rw-r--r-- | src/or/policies.c | 156 | ||||
-rw-r--r-- | src/or/policies.h | 29 | ||||
-rw-r--r-- | src/or/router.c | 2 |
5 files changed, 139 insertions, 61 deletions
diff --git a/src/or/config.c b/src/or/config.c index 22039b46ef..90284147f4 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -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(); diff --git a/src/or/config.h b/src/or/config.h index 51f7e90a2b..7e8868804e 100644 --- a/src/or/config.h +++ b/src/or/config.h @@ -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, diff --git a/src/or/policies.c b/src/or/policies.c index f5346329ad..91ca867783 100644 --- a/src/or/policies.c +++ b/src/or/policies.c @@ -62,14 +62,18 @@ 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, + 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); /** Replace all "private" entries in *<b>policy</b> with their expanded * equivalents. */ @@ -443,7 +447,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."); } @@ -993,16 +997,25 @@ 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 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 + * 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 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 @@ -1011,35 +1024,83 @@ exit_policy_remove_redundancies(smartlist_t *dest) * The list *dest is created as needed. */ void -policies_parse_exit_policy_reject_private(smartlist_t **dest, - int ipv6_exit, - uint32_t local_address, - tor_addr_t *ipv6_local_address, - int reject_interface_addresses) +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, + 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); - 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)); + 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 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 { - addr_policy_append_reject_addr(dest, ipv6_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 published IPv6 address", fmt_addr(ipv6_local_address)); + "our outbound IPv6 connection address", + fmt_addr(ipv6_outbound_address)); } } + /* 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 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); + } + } + } SMARTLIST_FOREACH_END(port); + } + /* Reject local addresses from public netblocks on any interface. */ if (reject_interface_addresses) { smartlist_t *public_addresses = NULL; @@ -1074,8 +1135,8 @@ policies_parse_exit_policy_reject_private(smartlist_t **dest, * * If <b>rejectprivate</b> is true: * - prepend "reject private:*" to the policy. - * - call policies_parse_exit_policy_reject_private to reject publicly - * routable addresses on this exit relay + * - 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 @@ -1092,8 +1153,11 @@ 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 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) { if (!ipv6_exit) { @@ -1103,9 +1167,13 @@ policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest, /* 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, local_address, - ipv6_local_address, - reject_interface_addresses); + policies_parse_exit_policy_reject_private( + dest, ipv6_exit, local_address, + ipv6_local_address, + ipv4_outbound_address, + ipv6_outbound_address, + reject_interface_addresses, + reject_configured_port_addresses); } if (parse_addr_policy(cfg, dest, -1)) return -1; @@ -1202,8 +1270,9 @@ 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 tor_addr_t *ipv6_local_address, + const tor_addr_t *ipv4_outbound_address, + const tor_addr_t *ipv6_outbound_address) { int ipv6_enabled = (options & EXIT_POLICY_IPV6_ENABLED) ? 1 : 0; int reject_private = (options & EXIT_POLICY_REJECT_PRIVATE) ? 1 : 0; @@ -1213,7 +1282,10 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, reject_private, local_address, ipv6_local_address, - reject_interface_addresses, + ipv4_outbound_address, + ipv6_outbound_address, + reject_private, + reject_private, add_default); } @@ -1241,8 +1313,7 @@ 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; @@ -1268,7 +1339,8 @@ policies_parse_exit_policy_from_options(const or_options_t *or_options, return policies_parse_exit_policy(or_options->ExitPolicy,result, parser_cfg,local_address, ipv6_local_address, - reject_interface_addresses); + &or_options->OutboundBindAddressIPv4_, + &or_options->OutboundBindAddressIPv6_); } /** Add "reject *:*" to the end of the policy in *<b>dest</b>, allocating diff --git a/src/or/policies.h b/src/or/policies.h index 97350f5751..26f92ad077 100644 --- a/src/or/policies.h +++ b/src/or/policies.h @@ -48,21 +48,26 @@ MOCK_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy, addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr, uint16_t port, const node_t *node); -int policies_parse_exit_policy_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); -void policies_parse_exit_policy_reject_private(smartlist_t **dest, - int ipv6_exit, - uint32_t local_address, - tor_addr_t *ipv6_local_address, - int reject_interface_addresses); + const tor_addr_t *ipv6_local_address, + const tor_addr_t *ipv4_outbound_address, + const tor_addr_t *ipv6_outbound_address); +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, + 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); diff --git a/src/or/router.c b/src/or/router.c index 1790416cf6..95e5ad8c30 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -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 = |