diff options
author | Sebastian Hahn <sebastian@torproject.org> | 2010-02-02 14:51:51 +0100 |
---|---|---|
committer | Sebastian Hahn <sebastian@torproject.org> | 2010-02-03 05:44:00 +0100 |
commit | 03bd98b3b1f92954c286f9d4dd5a2dd5f34a7e8b (patch) | |
tree | 83a87d83f12764ef97f0d72fd31fe5bd7943fe45 /src/or/policies.c | |
parent | c7a2efb380f08001bb27d8459fc1d16c7dfa40b4 (diff) | |
download | tor-03bd98b3b1f92954c286f9d4dd5a2dd5f34a7e8b.tar.gz tor-03bd98b3b1f92954c286f9d4dd5a2dd5f34a7e8b.zip |
Don't assign Exit flag incorrectly
exit_policy_is_general_exit() assumed that there are no redundancies
in the passed policy, in the sense that we actively combine entries
in the policy to really get rid of any redundancy. Since we cannot
do that without massively rewriting the policy lines the relay
operators set, fix exit_policy_is_general_exit().
Fixes bug 1238, discovered by Martin Kowalczyk.
Diffstat (limited to 'src/or/policies.c')
-rw-r--r-- | src/or/policies.c | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/src/or/policies.c b/src/or/policies.c index 453138eb46..ab308f764d 100644 --- a/src/or/policies.c +++ b/src/or/policies.c @@ -865,6 +865,43 @@ policies_set_router_exitpolicy_to_reject_all(routerinfo_t *r) smartlist_add(r->exit_policy, item); } +/** Return 1 if there is at least one /8 subnet in <b>policy</b> that + * allows exiting to <b>port</b>. */ +static int +exit_policy_is_general_exit_helper(smartlist_t *policy, int port) +{ + uint32_t j; + /* Is this /8 rejected (1), or undecided (0)? */ + char subnet_status[256]; + + memset(subnet_status, 0, sizeof(subnet_status)); + SMARTLIST_FOREACH(policy, addr_policy_t *, p, { + if (p->prt_min > port || p->prt_max < port) + continue; /* Doesn't cover our port. */ + for (j = 0; j < 256; ++j) { + tor_addr_t addr; + if (subnet_status[j] != 0) + continue; /* We already reject some part of this /8 */ + tor_addr_from_ipv4h(&addr, j<<24); + if (tor_addr_is_internal(&addr, 1)) /* 1 because * = 0.0.0.0 */ + continue; /* Local or non-routable addresses */ + if (tor_addr_compare_masked(&addr, &p->addr, p->maskbits, + CMP_EXACT) == 0) { + if (p->policy_type == ADDR_POLICY_ACCEPT) { + if (p->maskbits > 8) + continue; /* Narrower than a /8. */ + /* We found an allowed subnet of at least size /8. Done + * for this port! */ + return 1; + } else if (p->policy_type == ADDR_POLICY_REJECT) { + subnet_status[j] = 1; + } + } + } + }); + return 0; +} + /** 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. */ @@ -878,19 +915,7 @@ exit_policy_is_general_exit(smartlist_t *policy) return 0; for (i = 0; i < 3; ++i) { - SMARTLIST_FOREACH(policy, addr_policy_t *, p, { - if (p->prt_min > ports[i] || p->prt_max < ports[i]) - continue; /* Doesn't cover our port. */ - if (p->maskbits > 8) - continue; /* Narrower than a /8. */ - if (tor_addr_is_loopback(&p->addr)) - continue; /* 127.x or ::1. */ - /* We have a match that is at least a /8. */ - if (p->policy_type == ADDR_POLICY_ACCEPT) { - ++n_allowed; - break; /* stop considering this port */ - } - }); + n_allowed += exit_policy_is_general_exit_helper(policy, ports[i]); } return n_allowed >= 2; } |