diff options
author | teor (Tim Wilson-Brown) <teor2345@gmail.com> | 2015-09-11 15:10:54 +1000 |
---|---|---|
committer | teor (Tim Wilson-Brown) <teor2345@gmail.com> | 2015-09-16 00:13:03 +1000 |
commit | e033d5e90bcb63b68cfac07a4e041dd0ea839573 (patch) | |
tree | db28a5545407742ce86f0ea8a11406d10671b017 /src/or/routerparse.c | |
parent | 60312dc08b30243740e85c2a944874014f682579 (diff) | |
download | tor-e033d5e90bcb63b68cfac07a4e041dd0ea839573.tar.gz tor-e033d5e90bcb63b68cfac07a4e041dd0ea839573.zip |
Ignore accept6/reject6 IPv4, warn about unexpected rule outcomes
When parsing torrc ExitPolicies, we now warn if:
* an IPv4 address is used on an accept6 or reject6 line. The line is
ignored, but the rest of the policy items in the list are used.
(accept/reject continue to allow both IPv4 and IPv6 addresses in torrcs.)
* a "private" address alias is used on an accept6 or reject6 line.
The line filters both IPv4 and IPv6 private addresses, disregarding
the 6 in accept6/reject6.
When parsing torrc ExitPolicies, we now issue an info-level message:
* when expanding an accept/reject * line to include both IPv4 and IPv6
wildcard addresses.
In each instance, usage advice is provided to avoid the message.
Partial fix for ticket 16069. Patch by "teor".
Patch on 2eb7eafc9d78 and a96c0affcb4c (25 Oct 2012),
released in 0.2.4.7-alpha.
Diffstat (limited to 'src/or/routerparse.c')
-rw-r--r-- | src/or/routerparse.c | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/src/or/routerparse.c b/src/or/routerparse.c index d0b2cba19f..2f7e50e60a 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -3666,12 +3666,20 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos) * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or * ADDR_POLICY_REJECT) for items that specify no action. * + * Returns NULL on policy errors. + * + * If there is a policy error, malformed_list is set to true if the entire + * policy list should be discarded. Otherwise, it is set to false, and only + * this item should be ignored - the rest of the policy list can continue to + * be processed and used. + * * The addr_policy_t returned by this function can have its address set to * AF_UNSPEC for '*'. Use policy_expand_unspec() to turn this into a pair * of AF_INET and AF_INET6 items. */ MOCK_IMPL(addr_policy_t *, -router_parse_addr_policy_item_from_string,(const char *s, int assume_action)) +router_parse_addr_policy_item_from_string,(const char *s, int assume_action, + int *malformed_list)) { directory_token_t *tok = NULL; const char *cp, *eos; @@ -3688,6 +3696,8 @@ router_parse_addr_policy_item_from_string,(const char *s, int assume_action)) addr_policy_t *r; memarea_t *area = NULL; + tor_assert(malformed_list); + s = eat_whitespace(s); if ((*s == '*' || TOR_ISDIGIT(*s)) && assume_action >= 0) { if (tor_snprintf(line, sizeof(line), "%s %s", @@ -3714,9 +3724,32 @@ router_parse_addr_policy_item_from_string,(const char *s, int assume_action)) goto err; } + /* Use the extended interpretation of accept/reject *, + * expanding it into an IPv4 wildcard and an IPv6 wildcard. + * Also permit *4 and *6 for IPv4 and IPv6 only wildcards. */ r = router_parse_addr_policy(tok, TAPMP_EXTENDED_STAR); + if (!r) { + goto err; + } + + /* Ensure that accept6/reject6 fields are followed by IPv6 addresses. + * AF_UNSPEC addresses are only permitted on the accept/reject field type. + * Unlike descriptors, torrcs exit policy accept/reject can be followed by + * either an IPv4 or IPv6 address. */ + if ((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) && + tor_addr_family(&r->addr) != AF_INET6) { + /* This is a non-fatal error, just ignore this one entry. */ + *malformed_list = 0; + log_warn(LD_DIR, "IPv4 address '%s' with accept6/reject6 field type in " + "exit policy. Ignoring, but continuing to parse rules. (Use " + "accept/reject with IPv4 addresses.)", + tok->n_args == 1 ? tok->args[0] : ""); + return NULL; + } + goto done; err: + *malformed_list = 1; r = NULL; done: token_clear(tok); @@ -3733,19 +3766,26 @@ static int router_add_exit_policy(routerinfo_t *router, directory_token_t *tok) { addr_policy_t *newe; + /* Use the standard interpretation of accept/reject *, an IPv4 wildcard. */ newe = router_parse_addr_policy(tok, 0); if (!newe) return -1; if (! router->exit_policy) router->exit_policy = smartlist_new(); + /* Ensure that in descriptors, accept/reject fields are followed by + * IPv4 addresses, and accept6/reject6 fields are followed by + * IPv6 addresses. Unlike torrcs, descriptor exit policies do not permit + * accept/reject followed by IPv6. */ if (((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) && tor_addr_family(&newe->addr) == AF_INET) || ((tok->tp == K_ACCEPT || tok->tp == K_REJECT) && tor_addr_family(&newe->addr) == AF_INET6)) { + /* There's nothing the user can do about other relays' descriptors, + * so we don't provide usage advice here. */ log_warn(LD_DIR, "Mismatch between field type and address type in exit " - "policy"); + "policy '%s'. Ignoring.", tok->n_args == 1 ? tok->args[0] : ""); addr_policy_free(newe); return -1; } @@ -3821,6 +3861,13 @@ router_parse_addr_policy_private(directory_token_t *tok) result.prt_min = port_min; result.prt_max = port_max; + if (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) { + log_warn(LD_GENERAL, + "'%s' expands into rules which apply to all private IPv4 and " + "IPv6 addresses. (Use accept/reject private:* for IPv4 and " + "IPv6.)", tok->n_args == 1 ? tok->args[0] : ""); + } + return addr_policy_get_canonical_entry(&result); } |