summaryrefslogtreecommitdiff
path: root/src/or/routerlist.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2005-01-20 18:39:48 +0000
committerNick Mathewson <nickm@torproject.org>2005-01-20 18:39:48 +0000
commit129e754ae42db3ceb57a21c20affa094b02a9f7f (patch)
treed6a1c74216088edcafb1a1758ce9201e5856c0d4 /src/or/routerlist.c
parentdab63afe2f03ffb8be632cb8cedc0fabd1deb5b3 (diff)
downloadtor-129e754ae42db3ceb57a21c20affa094b02a9f7f.tar.gz
tor-129e754ae42db3ceb57a21c20affa094b02a9f7f.zip
Warn when exit policy implicitly allows local addresses.
svn:r3383
Diffstat (limited to 'src/or/routerlist.c')
-rw-r--r--src/or/routerlist.c84
1 files changed, 84 insertions, 0 deletions
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 <b>policy</b> implicitly allows connections to any port in the
+ * IP set <b>addr</b>/<b>mask</b>, then set *<b>policy_out</b> to the
+ * part of the policy that allows it, and return 1. Else return 0.
+ *
+ * A policy allows an IP:Port combination <em>implicitly</em> 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 <b>policy</b> implicitly allows connections to any port on
+ * 127.*, 192.168.*, etc, then warn (if <b>warn</b> 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 <b>router</b> does not permit exit streams.
*/
int router_exit_policy_rejects_all(routerinfo_t *router) {