From 129e754ae42db3ceb57a21c20affa094b02a9f7f Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 20 Jan 2005 18:39:48 +0000 Subject: [PATCH] Warn when exit policy implicitly allows local addresses. svn:r3383 --- src/or/config.c | 1 + src/or/or.h | 2 ++ src/or/routerlist.c | 84 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/src/or/config.c b/src/or/config.c index b0cf8474c6..3175e13a11 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1480,6 +1480,7 @@ options_validate(or_options_t *options) log_fn(LOG_WARN, "Error in Exit Policy entry."); result = -1; } + exit_policy_implicitly_allows_local_networks(addr_policy, 1); if (config_parse_addr_policy(options->DirPolicy, &addr_policy)) { log_fn(LOG_WARN, "Error in DirPolicy entry."); result = -1; diff --git a/src/or/or.h b/src/or/or.h index 30ee523337..a525f2ca38 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1615,6 +1615,8 @@ void add_nickname_list_to_smartlist(struct smartlist_t *sl, const char *list, in int router_nickname_is_in_list(routerinfo_t *router, const char *list); routerinfo_t *routerlist_find_my_routerinfo(void); int router_nickname_matches(routerinfo_t *router, const char *nickname); +int exit_policy_implicitly_allows_local_networks(addr_policy_t *policy, + int warn); /** How many seconds a router must be up before we'll use it for * reliability-critical node positions. diff --git a/src/or/routerlist.c b/src/or/routerlist.c index c4411fdcdc..f9c39eca55 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -1021,6 +1021,90 @@ int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port, return 1; /* all will reject. */ } +/** + * If policy implicitly allows connections to any port in the + * IP set addr/mask, then set *policy_out to the + * part of the policy that allows it, and return 1. Else return 0. + * + * A policy allows an IP:Port combination implicitly if + * it is included in a *: pattern, or in a fallback pattern. + */ +static int +policy_includes_addr_mask_implicitly(addr_policy_t *policy, + uint32_t addr, uint32_t mask, + addr_policy_t **policy_out) +{ + uint32_t addr2; + tor_assert(policy_out); + addr &= mask; + addr2 = addr | ~mask; + for (; policy; policy=policy->next) { + /* Does this policy cover all of the address range we're looking at? */ + /* Boolean logic time: range X is contained in range Y if, for + * each bit B, all possible values of B in X are values of B in Y. + * In "addr", we have every fixed bit set to its value, and every + * free bit set to 0. In "addr2", we have every fixed bit set to + * its value, and every free bit set to 1. So if addr and addr2 are + * both in the policy, the range is covered by the policy. + */ + if ((policy->addr & policy->msk) == (addr & policy->msk) && + (policy->addr & policy->msk) == (addr2 & policy->msk) && + (policy->prt_min <= 1 && policy->prt_max == 65535)) { + return 0; + } + /* Does this policy cover some of the address range we're looking at? */ + /* Boolean logic time: range X and range Y intersect if there is + * some z such that z & Xmask == Xaddr and z & Ymask == Yaddr. + * This is FALSE iff there is some bit b where Xmask == yMask == 1 + * and Xaddr != Yaddr. So if X intersects with Y iff at every + * place where Xmask&Ymask==1, Xaddr == Yaddr, or equivalently, + * Xaddr&Xmask&Ymask == Yaddr&Xmask&Ymask. + */ + if ((policy->addr & policy->msk & mask) == (addr & policy->msk) && + policy->policy_type == ADDR_POLICY_ACCEPT) { + *policy_out = policy; + return 1; + } + } + *policy_out = NULL; + return 1; +} + +/** If policy implicitly allows connections to any port on + * 127.*, 192.168.*, etc, then warn (if warn is set) and return + * true. Else return false. + **/ +int +exit_policy_implicitly_allows_local_networks(addr_policy_t *policy, + int warn) +{ + addr_policy_t *p; + int r=0,i; + static struct { + uint32_t addr; uint32_t mask; const char *network; + } private_networks[] = { + { 0x7f000000, 0xff000000, "localhost (127.x)" }, + { 0x0a000000, 0xff000000, "addresses in private network 10.x" }, + { 0xa9fe0000, 0xffff0000, "addresses in private network 169.254.x" }, + { 0xac100000, 0xfff00000, "addresses in private network 172.16.x" }, + { 0xc0a80000, 0xffff0000, "addresses in private network 192.168.x" }, + { 0,0,NULL}, + }; + for (i=0; private_networks[i].addr; ++i) { + p = NULL; + if (policy_includes_addr_mask_implicitly( + policy, private_networks[i].addr, private_networks[i].mask, &p)) { + if (warn) + log_fn(LOG_WARN, "Exit policy %s implicitly accepts %s", + policy?policy->string:"(default)", + private_networks[i].network); + r = 1; + } + } + + return r; +} + /** Return true iff router does not permit exit streams. */ int router_exit_policy_rejects_all(routerinfo_t *router) {