From b88c4ba11c4d889b0071c39b3d383e897610f9ab Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sat, 19 Mar 2005 06:57:16 +0000 Subject: [PATCH] Turn addr_policy_compare from a tristate to a quadstate; this should help address our "Ah, you allow 1.2.3.4:80. You are a good choice for google.com" problem. svn:r3786 --- src/or/circuitbuild.c | 5 +++-- src/or/circuituse.c | 20 ++++++++++++------- src/or/connection_edge.c | 15 +++++++------- src/or/directory.c | 5 ++--- src/or/or.h | 14 +++++++++----- src/or/router.c | 7 ++++--- src/or/routerlist.c | 42 ++++++++++++++++++++++++++-------------- 7 files changed, 66 insertions(+), 42 deletions(-) diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 83fc795862..7e01fc3d36 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -858,10 +858,11 @@ router_handles_some_port(routerinfo_t *router, smartlist_t *needed_ports) { uint16_t port; for (i = 0; i < smartlist_len(needed_ports); ++i) { + addr_policy_result_t r; port = *(uint16_t *)smartlist_get(needed_ports, i); tor_assert(port); - if (router_compare_addr_to_addr_policy(0, port, router->exit_policy) != - ADDR_POLICY_REJECTED) + r = router_compare_addr_to_addr_policy(0, port, router->exit_policy); + if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED) return 1; } return 0; diff --git a/src/or/circuituse.c b/src/or/circuituse.c index b7e2f914dd..836bb66b70 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -291,13 +291,19 @@ int circuit_stream_is_being_handled(connection_t *conn, uint16_t port, int min) circ->timestamp_dirty + get_options()->MaxCircuitDirtiness < now)) { exitrouter = router_get_by_digest(circ->build_state->chosen_exit_digest); if (exitrouter && - (!need_uptime || circ->build_state->need_uptime) && - ((conn && connection_ap_can_use_exit(conn, exitrouter)) || - (!conn && - router_compare_addr_to_addr_policy(0, port, exitrouter->exit_policy) != - ADDR_POLICY_REJECTED))) { - if (++num >= min) - return 1; + (!need_uptime || circ->build_state->need_uptime)) { + int ok; + if (conn) { + ok = connection_ap_can_use_exit(conn, exitrouter); + } else { + addr_policy_result_t r = + router_compare_addr_to_addr_policy(0, port, exitrouter->exit_policy); + ok = r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED; + } + if (ok) { + if (++num >= min) + return 1; + } } } } diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 8bce01ed3a..5550e55518 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1471,8 +1471,8 @@ int connection_edge_is_rendezvous_stream(connection_t *conn) { return 0; } -/** Return 1 if router exit might allow stream conn - * to exit from it, or 0 if it definitely will not allow it. +/** Return 1 if router exit is likely to allow stream conn + * to exit from it, or 0 if it probably will not allow it. * (We might be uncertain if conn's destination address has not yet been * resolved.) */ @@ -1502,10 +1502,12 @@ int connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit) if (conn->socks_request->command != SOCKS_COMMAND_RESOLVE) { struct in_addr in; uint32_t addr = 0; + addr_policy_result_t r; if (tor_inet_aton(conn->socks_request->address, &in)) addr = ntohl(in.s_addr); - if (router_compare_addr_to_addr_policy(addr, conn->socks_request->port, - exit->exit_policy) == ADDR_POLICY_REJECTED) + r = router_compare_addr_to_addr_policy(addr, conn->socks_request->port, + exit->exit_policy); + if (r == ADDR_POLICY_REJECTED || r == ADDR_POLICY_PROBABLY_REJECTED) return 0; } return 1; @@ -1550,11 +1552,10 @@ int socks_policy_permits_address(uint32_t addr) if (!socks_policy) /* 'no socks policy' means 'accept' */ return 1; a = router_compare_addr_to_addr_policy(addr, 1, socks_policy); - if (a==-1) + if (a==ADDR_POLICY_REJECTED) return 0; - else if (a==0) + else if (a==ADDR_POLICY_ACCEPTED) return 1; - tor_assert(a==1); log_fn(LOG_WARN, "Bug: Got unexpected 'maybe' answer from socks policy"); return 0; } diff --git a/src/or/directory.c b/src/or/directory.c index fd9fc6371d..2b5c84b155 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -100,11 +100,10 @@ int dir_policy_permits_address(uint32_t addr) if (!dir_policy) /* 'no dir policy' means 'accept' */ return 1; a = router_compare_addr_to_addr_policy(addr, 1, dir_policy); - if (a==-1) + if (a==ADDR_POLICY_REJECTED) return 0; - else if (a==0) + else if (a==ADDR_POLICY_ACCEPTED) return 1; - tor_assert(a==1); log_fn(LOG_WARN, "Bug: got unexpected 'maybe' answer from dir policy"); return 0; } diff --git a/src/or/or.h b/src/or/or.h index c802401964..0a8d6610f4 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1661,6 +1661,12 @@ int rend_mid_establish_rendezvous(circuit_t *circ, const char *request, size_t r int rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len); /********************************* router.c ***************************/ +typedef enum { + ADDR_POLICY_ACCEPTED=0, + ADDR_POLICY_REJECTED=-1, + ADDR_POLICY_PROBABLY_ACCEPTED=1, + ADDR_POLICY_PROBABLY_REJECTED=2 +} addr_policy_result_t; void set_onion_key(crypto_pk_env_t *k); crypto_pk_env_t *get_onion_key(void); @@ -1760,11 +1766,9 @@ void routerlist_remove_old_routers(int age); int router_load_single_router(const char *s); int router_load_routerlist_from_directory(const char *s,crypto_pk_env_t *pkey, int dir_is_recent, int dir_is_cached); -int router_compare_addr_to_addr_policy(uint32_t addr, uint16_t port, - addr_policy_t *policy); -#define ADDR_POLICY_ACCEPTED 0 -#define ADDR_POLICY_REJECTED -1 -#define ADDR_POLICY_UNKNOWN 1 +addr_policy_result_t router_compare_addr_to_addr_policy(uint32_t addr, + uint16_t port, addr_policy_t *policy); + int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port, int need_uptime); diff --git a/src/or/router.c b/src/or/router.c index e0b500f869..e2263eef81 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -581,8 +581,8 @@ static void router_add_exit_policy_from_config(routerinfo_t *router) { config_parse_addr_policy(&default_policy, &router->exit_policy); } -/** OR only: Return false if my exit policy says to allow connection to - * conn. Else return true. +/** OR only: Check whether my exit policy says to allow connection to + * conn. Return false if we accept; true if we reject. */ int router_compare_to_my_exit_policy(connection_t *conn) { @@ -594,10 +594,11 @@ int router_compare_to_my_exit_policy(connection_t *conn) return -1; return router_compare_addr_to_addr_policy(conn->addr, conn->port, - desc_routerinfo->exit_policy); + desc_routerinfo->exit_policy) != ADDR_POLICY_ACCEPTED; } + /** Return true iff router has the same nickname as this OR. (For an * OP, always returns false.) */ diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 5f7df4fb54..0ae62ad308 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -1001,16 +1001,26 @@ router_resolve_routerlist(routerlist_t *rl) return 0; } -/** Decide whether a given addr:port is definitely accepted, definitely - * rejected, or neither by a given policy. If addr is 0, we - * don't know the IP of the target address. If port is 0, we - * don't know the port of the target address. +/** Decide whether a given addr:port is definitely accepted, + * definitely rejected, probably accepted, or probably rejected by a + * given policy. If addr is 0, we don't know the IP of the + * target address. If port is 0, we don't know the port of the + * target address. * - * Returns -1 for "rejected", 0 for "accepted", 1 for "maybe" (since IP or - * port is unknown). + * For now, the algorithm is pretty simple: we look for definite and + * uncertain matches. The first definite match is what we guess; if + * it was proceded by no uncertain matches of the opposite policy, + * then the guess is definite; otherwise it is probable. (If we + * have a known addr and port, all matches are definite; if we have an + * unknown addr/port, any address/port ranges other than "all" are + * uncertain.) + * + * We could do better by assuming that some ranges never match typical + * addresses (127.0.0.1, and so on). But we'll try this for now. */ -int router_compare_addr_to_addr_policy(uint32_t addr, uint16_t port, - addr_policy_t *policy) +addr_policy_result_t +router_compare_addr_to_addr_policy(uint32_t addr, uint16_t port, + addr_policy_t *policy) { int maybe_reject = 0; int maybe_accept = 0; @@ -1060,14 +1070,14 @@ int router_compare_addr_to_addr_policy(uint32_t addr, uint16_t port, if (tmpe->policy_type == ADDR_POLICY_ACCEPT) { /* If we already hit a clause that might trigger a 'reject', than we * can't be sure of this certain 'accept'.*/ - return maybe_reject ? ADDR_POLICY_UNKNOWN : ADDR_POLICY_ACCEPTED; + return maybe_reject ? ADDR_POLICY_PROBABLY_ACCEPTED : ADDR_POLICY_ACCEPTED; } else { - return maybe_accept ? ADDR_POLICY_UNKNOWN : ADDR_POLICY_REJECTED; + return maybe_accept ? ADDR_POLICY_PROBABLY_REJECTED : ADDR_POLICY_REJECTED; } } } /* accept all by default. */ - return maybe_reject ? ADDR_POLICY_UNKNOWN : ADDR_POLICY_ACCEPTED; + return maybe_reject ? ADDR_POLICY_PROBABLY_ACCEPTED : ADDR_POLICY_ACCEPTED; } /** Return 1 if all running sufficiently-stable routers will reject @@ -1076,15 +1086,17 @@ int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port, int need_uptime) { int i; routerinfo_t *router; + addr_policy_result_t r; if (!routerlist) return 1; for (i=0;irouters);i++) { router = smartlist_get(routerlist->routers, i); if (router->is_running && - !router_is_unreliable(router, need_uptime, 0) && - router_compare_addr_to_addr_policy( - addr, port, router->exit_policy) != ADDR_POLICY_REJECTED) - return 0; /* this one could be ok. good enough. */ + !router_is_unreliable(router, need_uptime, 0)) { + r = router_compare_addr_to_addr_policy(addr, port, router->exit_policy); + if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED) + return 0; /* this one could be ok. good enough. */ + } } return 1; /* all will reject. */ }