[tor-commits] [tor/master] ExitPolicy accept6/reject6 produces IPv6 wildcard addresses only

nickm at torproject.org nickm at torproject.org
Wed Sep 16 12:35:38 UTC 2015


commit d3358a0a05f661f78286d43fcc71d79daa090460
Author: teor (Tim Wilson-Brown) <teor2345 at gmail.com>
Date:   Mon Sep 14 11:46:58 2015 +1000

    ExitPolicy accept6/reject6 produces IPv6 wildcard addresses only
    
    In previous versions of Tor, ExitPolicy accept6/reject6 * produced
    policy entries for IPv4 and IPv6 wildcard addresses.
    
    To reduce operator confusion, change accept6/reject6 * to only produce
    an IPv6 wildcard address.
    
    Resolves bug #16069.
    
    Patch on 2eb7eafc9d78 and a96c0affcb4c (25 Oct 2012),
    released in 0.2.4.7-alpha.
---
 changes/bug16069-exit-policy-rule6  |    4 +++-
 doc/tor.1.txt                       |   32 +++++++++++++++++--------
 src/common/address.c                |   36 +++++++++++++++++++++-------
 src/common/address.h                |   11 ++++++++-
 src/config/torrc.minimal.in-staging |    9 ++++---
 src/config/torrc.sample.in          |    9 ++++---
 src/or/routerparse.c                |   11 ++++++++-
 src/test/test_policy.c              |   44 ++++++++++++++++++++++++++++++++---
 8 files changed, 126 insertions(+), 30 deletions(-)

diff --git a/changes/bug16069-exit-policy-rule6 b/changes/bug16069-exit-policy-rule6
index 5e7b894..a8d7e70 100644
--- a/changes/bug16069-exit-policy-rule6
+++ b/changes/bug16069-exit-policy-rule6
@@ -1,4 +1,6 @@
   o Minor bug fixes (torrc exit policies):
+    - accept6/reject6 * lines only produce IPv6 wildcard addresses,
+      previously they would produce both IPv4 and IPv6 wildcard addresses.
     - 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.
@@ -13,6 +15,6 @@
       * 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".
+      Resolves ticket 16069. Patch by "teor".
       Patch on 2eb7eafc9d78 and a96c0affcb4c (25 Oct 2012),
       released in 0.2.4.7-alpha.
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 89673a8..4f922c8 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -1537,12 +1537,26 @@ is non-zero):
     "\*". +
  +
     For example, "accept 18.7.22.69:\*,reject 18.0.0.0/8:\*,accept \*:\*" would
-    reject any traffic destined for MIT except for web.mit.edu, and accept
-    anything else. +
+    reject any IPv4 traffic destined for MIT except for web.mit.edu, and accept
+    any other IPv4 or IPv6 traffic. +
  +
-    To specify all internal and link-local networks (including 0.0.0.0/8,
-    169.254.0.0/16,    127.0.0.0/8,    192.168.0.0/16, 10.0.0.0/8, and
-    172.16.0.0/12), you can use the "private" alias instead of an address.
+    Tor also allows IPv6 exit policy entries. For instance, "reject6 [FC00::]/7:*"
+    rejects all destinations that share 7 most significant bit prefix with
+    address FC00::. Respectively, "accept6 [C000::]/3:*" accepts all destinations
+    that share 3 most significant bit prefix with address C000::. +
+ +
+    accept6 and reject6 only produce IPv6 exit policy entries. Using an IPv4
+    address with accept6 or reject6 is ignored and generates a warning.
+    accept/reject allows either IPv4 or IPv6 addresses. Use *4 as an IPv4
+    wildcard address, and *6 as an IPv6 wildcard address. accept/reject *
+    expands to matching IPv4 and IPv6 wildcard address rules. +
+ +
+    To specify all IPv4 and IPv6 internal and link-local networks (including
+    0.0.0.0/8, 169.254.0.0/16, 127.0.0.0/8, 192.168.0.0/16, 10.0.0.0/8,
+    172.16.0.0/12, [::]/8, [FC00::]/7, [FE80::]/10, [FEC0::]/10, [FF00::]/8,
+    and [::]/127), you can use the "private" alias instead of an address.
+    ("private" always produces rules for IPv4 and IPv6 addresses, even when
+    used with accept6/reject6.)
     These addresses are rejected by default (at the beginning of your exit
     policy), along with your public IP address, unless you set the
     ExitPolicyRejectPrivate config option to 0. For example, once you've done
@@ -1552,11 +1566,6 @@ is non-zero):
     public (external) IP address. See RFC 1918 and RFC 3330 for more details
     about internal and reserved IP address space. +
  +
-    Tor also allow IPv6 exit policy entries. For instance, "reject6 [FC00::]/7:*"
-    rejects all destinations that share 7 most significant bit prefix with 
-    address FC00::. Respectively, "accept6 [C000::]/3:*" accepts all destinations
-    that share 3 most significant bit prefix with address C000::. +
- +
     This directive can be specified multiple times so you don't have to put it
     all on one line. +
  +
@@ -1577,6 +1586,9 @@ is non-zero):
        reject *:6881-6999
        accept *:*
 
+    Since the default exit policy uses accept/reject *, it applies to both
+    IPv4 and IPv6 addresses.
+
 [[ExitPolicyRejectPrivate]] **ExitPolicyRejectPrivate** **0**|**1**::
     Reject all private (local) networks, along with your own public IP address,
     at the beginning of your exit policy. See above entry on ExitPolicy.
diff --git a/src/common/address.c b/src/common/address.c
index 597f699..0663553 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -620,13 +620,20 @@ tor_addr_to_PTR_name(char *out, size_t outlen,
  *  yield an IPv4 wildcard.
  *
  *  If 'flags & TAPMP_EXTENDED_STAR' is true, then the wildcard address '*'
- *  yields an AF_UNSPEC wildcard address, and the following change is made
+ *  yields an AF_UNSPEC wildcard address, which expands to corresponding
+ *  wildcard IPv4 and IPv6 rules, and the following change is made
  *  in the grammar above:
  *   Address ::= IPv4Address / "[" IPv6Address "]" / "*" / "*4" / "*6"
  *  with the new "*4" and "*6" productions creating a wildcard to match
  *  IPv4 or IPv6 addresses.
  *
- */
+ *  If 'flags & TAPMP_EXTENDED_STAR' and 'flags & TAPMP_STAR_IPV4_ONLY' are
+ *  both true, then the wildcard address '*' yields an IPv4 wildcard.
+ *
+ *  If 'flags & TAPMP_EXTENDED_STAR' and 'flags & TAPMP_STAR_IPV6_ONLY' are
+ *  both true, then the wildcard address '*' yields an IPv6 wildcard.
+ *
+ * TAPMP_STAR_IPV4_ONLY and TAPMP_STAR_IPV6_ONLY are mutually exclusive. */
 int
 tor_addr_parse_mask_ports(const char *s,
                           unsigned flags,
@@ -643,6 +650,10 @@ tor_addr_parse_mask_ports(const char *s,
 
   tor_assert(s);
   tor_assert(addr_out);
+  /* We can either only want an IPv4 address or only want an IPv6 address,
+   * but we can't only want IPv4 & IPv6 at the same time. */
+  tor_assert(!((flags & TAPMP_STAR_IPV4_ONLY)
+               && (flags & TAPMP_STAR_IPV6_ONLY)));
 
   /** Longest possible length for an address, mask, and port-range combination.
    * Includes IP, [], /mask, :, ports */
@@ -688,12 +699,21 @@ tor_addr_parse_mask_ports(const char *s,
 
   if (!strcmp(address, "*")) {
     if (flags & TAPMP_EXTENDED_STAR) {
-      family = AF_UNSPEC;
-      tor_addr_make_unspec(addr_out);
-      log_info(LD_GENERAL,
-               "'%s' expands into rules which apply to all IPv4 and IPv6 "
-               "addresses. (Use accept/reject *4:* for IPv4 or "
-               "accept[6]/reject[6] *6:* for IPv6.)", s);
+      if (flags & TAPMP_STAR_IPV4_ONLY) {
+        family = AF_INET;
+        tor_addr_from_ipv4h(addr_out, 0);
+      } else if (flags & TAPMP_STAR_IPV6_ONLY) {
+        static char nil_bytes[16] = { [0]=0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
+        family = AF_INET6;
+        tor_addr_from_ipv6_bytes(addr_out, nil_bytes);
+      } else {
+        family = AF_UNSPEC;
+        tor_addr_make_unspec(addr_out);
+        log_info(LD_GENERAL,
+                 "'%s' expands into rules which apply to all IPv4 and IPv6 "
+                 "addresses. (Use accept/reject *4:* for IPv4 or "
+                 "accept[6]/reject[6] *6:* for IPv6.)", s);
+      }
     } else {
       family = AF_INET;
       tor_addr_from_ipv4h(addr_out, 0);
diff --git a/src/common/address.h b/src/common/address.h
index 48a34ce..90207c3 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -227,10 +227,19 @@ int tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
 
 int tor_addr_port_lookup(const char *s, tor_addr_t *addr_out,
                         uint16_t *port_out);
-/* Does the address * yield an AF_UNSPEC wildcard address (1) and do we
+
+/* Does the address * yield an AF_UNSPEC wildcard address (1),
+ * which expands to corresponding wildcard IPv4 and IPv6 rules, and do we
  * allow *4 and *6 for IPv4 and IPv6 wildcards, respectively;
  * or does the address * yield IPv4 wildcard address (0).  */
 #define TAPMP_EXTENDED_STAR 1
+/* Does the address * yield an IPv4 wildcard address rule (1);
+ * or does it yield wildcard IPv4 and IPv6 rules (0) */
+#define TAPMP_STAR_IPV4_ONLY     (1 << 1)
+/* Does the address * yield an IPv6 wildcard address rule (1);
+ * or does it yield wildcard IPv4 and IPv6 rules (0) */
+#define TAPMP_STAR_IPV6_ONLY     (1 << 2)
+/* TAPMP_STAR_IPV4_ONLY and TAPMP_STAR_IPV6_ONLY are mutually exclusive. */
 int tor_addr_parse_mask_ports(const char *s, unsigned flags,
                               tor_addr_t *addr_out, maskbits_t *mask_out,
                               uint16_t *port_min_out, uint16_t *port_max_out);
diff --git a/src/config/torrc.minimal.in-staging b/src/config/torrc.minimal.in-staging
index d54a559..c17f7eb 100644
--- a/src/config/torrc.minimal.in-staging
+++ b/src/config/torrc.minimal.in-staging
@@ -1,5 +1,5 @@
 ## Configuration file for a typical Tor user
-## Last updated 2 September 2014 for Tor 0.2.6.1-alpha.
+## Last updated 11 September 2015 for Tor 0.2.7.3-alpha.
 ## (may or may not work for much older or much newer versions of Tor.)
 ##
 ## Lines that begin with "## " try to explain what's going on. Lines
@@ -24,6 +24,7 @@
 ## can access your SocksPort may be able to learn about the connections
 ## you make.
 #SocksPolicy accept 192.168.0.0/16
+#SocksPolicy accept6 FC00::/7
 #SocksPolicy reject *
 
 ## Logs go to stdout at level "notice" unless redirected by something
@@ -174,8 +175,10 @@
 ## networks, including to your public IP address. See the man page entry
 ## for ExitPolicyRejectPrivate if you want to allow "exit enclaving".
 ##
-#ExitPolicy accept *:6660-6667,reject *:* # allow irc ports but no more
-#ExitPolicy accept *:119 # accept nntp as well as default exit policy
+#ExitPolicy accept *:6660-6667,reject *:* # allow irc ports on IPv4 and IPv6 but no more
+#ExitPolicy accept *:119 # accept nntp ports on IPv4 and IPv6 as well as default exit policy
+#ExitPolicy accept *4:119 # accept nntp ports on IPv4 only as well as default exit policy
+#ExitPolicy accept6 *6:119 # accept nntp ports on IPv6 only as well as default exit policy
 #ExitPolicy reject *:* # no exits allowed
 
 ## Bridge relays (or "bridges") are Tor relays that aren't listed in the
diff --git a/src/config/torrc.sample.in b/src/config/torrc.sample.in
index d54a559..c17f7eb 100644
--- a/src/config/torrc.sample.in
+++ b/src/config/torrc.sample.in
@@ -1,5 +1,5 @@
 ## Configuration file for a typical Tor user
-## Last updated 2 September 2014 for Tor 0.2.6.1-alpha.
+## Last updated 11 September 2015 for Tor 0.2.7.3-alpha.
 ## (may or may not work for much older or much newer versions of Tor.)
 ##
 ## Lines that begin with "## " try to explain what's going on. Lines
@@ -24,6 +24,7 @@
 ## can access your SocksPort may be able to learn about the connections
 ## you make.
 #SocksPolicy accept 192.168.0.0/16
+#SocksPolicy accept6 FC00::/7
 #SocksPolicy reject *
 
 ## Logs go to stdout at level "notice" unless redirected by something
@@ -174,8 +175,10 @@
 ## networks, including to your public IP address. See the man page entry
 ## for ExitPolicyRejectPrivate if you want to allow "exit enclaving".
 ##
-#ExitPolicy accept *:6660-6667,reject *:* # allow irc ports but no more
-#ExitPolicy accept *:119 # accept nntp as well as default exit policy
+#ExitPolicy accept *:6660-6667,reject *:* # allow irc ports on IPv4 and IPv6 but no more
+#ExitPolicy accept *:119 # accept nntp ports on IPv4 and IPv6 as well as default exit policy
+#ExitPolicy accept *4:119 # accept nntp ports on IPv4 only as well as default exit policy
+#ExitPolicy accept6 *6:119 # accept nntp ports on IPv6 only as well as default exit policy
 #ExitPolicy reject *:* # no exits allowed
 
 ## Bridge relays (or "bridges") are Tor relays that aren't listed in the
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 2f7e50e..7bb18ec 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -3820,6 +3820,12 @@ router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags)
   else
     newe.policy_type = ADDR_POLICY_ACCEPT;
 
+  /* accept6/reject6 * produces an IPv6 wildcard address only.
+   * (accept/reject * produces rules for IPv4 and IPv6 wildcard addresses.) */
+  if (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) {
+    fmt_flags |= TAPMP_STAR_IPV6_ONLY;
+  }
+
   if (tor_addr_parse_mask_ports(arg, fmt_flags, &newe.addr, &newe.maskbits,
                                 &newe.prt_min, &newe.prt_max) < 0) {
     log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg));
@@ -3829,9 +3835,12 @@ router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags)
   return addr_policy_get_canonical_entry(&newe);
 }
 
-/** Parse an exit policy line of the format "accept/reject private:...".
+/** Parse an exit policy line of the format "accept[6]/reject[6] private:...".
  * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
  * router descriptors until earlier versions are obsolete.
+ *
+ * accept/reject and accept6/reject6 private all produce rules for both
+ * IPv4 and IPv6 addresses.
  */
 static addr_policy_t *
 router_parse_addr_policy_private(directory_token_t *tok)
diff --git a/src/test/test_policy.c b/src/test/test_policy.c
index 5e91468..4150b97 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -77,7 +77,8 @@ test_policies_general(void *arg)
   int i;
   smartlist_t *policy = NULL, *policy2 = NULL, *policy3 = NULL,
               *policy4 = NULL, *policy5 = NULL, *policy6 = NULL,
-              *policy7 = NULL;
+              *policy7 = NULL, *policy8 = NULL, *policy9 = NULL,
+              *policy10 = NULL, *policy11 = NULL;
   addr_policy_t *p;
   tor_addr_t tar;
   config_line_t line;
@@ -192,6 +193,30 @@ test_policies_general(void *arg)
   tt_assert(p != NULL);
   smartlist_add(policy7, p);
 
+  tt_int_op(0, OP_EQ, policies_parse_exit_policy(NULL, &policy8,
+                                                 EXIT_POLICY_IPV6_ENABLED |
+                                                 EXIT_POLICY_REJECT_PRIVATE |
+                                                 EXIT_POLICY_ADD_DEFAULT, 0));
+
+  tt_assert(policy8);
+
+  tt_int_op(0, OP_EQ, policies_parse_exit_policy(NULL, &policy9,
+                                                 EXIT_POLICY_REJECT_PRIVATE |
+                                                 EXIT_POLICY_ADD_DEFAULT, 0));
+
+  tt_assert(policy9);
+
+  /* accept6 * and reject6 * produce IPv6 wildcards only */
+  policy10 = smartlist_new();
+  p = router_parse_addr_policy_item_from_string("accept6 *:*",-1);
+  tt_assert(p != NULL);
+  smartlist_add(policy10, p);
+
+  policy11 = smartlist_new();
+  p = router_parse_addr_policy_item_from_string("reject6 *:*",-1);
+  tt_assert(p != NULL);
+  smartlist_add(policy11, p);
+
   tt_assert(!exit_policy_is_general_exit(policy));
   tt_assert(exit_policy_is_general_exit(policy2));
   tt_assert(!exit_policy_is_general_exit(NULL));
@@ -200,6 +225,10 @@ test_policies_general(void *arg)
   tt_assert(!exit_policy_is_general_exit(policy5));
   tt_assert(!exit_policy_is_general_exit(policy6));
   tt_assert(!exit_policy_is_general_exit(policy7));
+  tt_assert(exit_policy_is_general_exit(policy8));
+  tt_assert(exit_policy_is_general_exit(policy9));
+  tt_assert(!exit_policy_is_general_exit(policy10));
+  tt_assert(!exit_policy_is_general_exit(policy11));
 
   tt_assert(cmp_addr_policies(policy, policy2));
   tt_assert(cmp_addr_policies(policy, NULL));
@@ -208,7 +237,12 @@ test_policies_general(void *arg)
 
   tt_assert(!policy_is_reject_star(policy2, AF_INET));
   tt_assert(policy_is_reject_star(policy, AF_INET));
+  tt_assert(policy_is_reject_star(policy10, AF_INET));
+  tt_assert(!policy_is_reject_star(policy10, AF_INET6));
+  tt_assert(policy_is_reject_star(policy11, AF_INET));
+  tt_assert(policy_is_reject_star(policy11, AF_INET6));
   tt_assert(policy_is_reject_star(NULL, AF_INET));
+  tt_assert(policy_is_reject_star(NULL, AF_INET6));
 
   addr_policy_list_free(policy);
   policy = NULL;
@@ -219,13 +253,13 @@ test_policies_general(void *arg)
   line.value = (char*)"accept *:80,reject private:*,reject *:*";
   line.next = NULL;
   tt_int_op(0, OP_EQ, policies_parse_exit_policy(&line,&policy,
-                                              EXIT_POLICY_IPV6_ENABLED |
+                                              ~EXIT_POLICY_IPV6_ENABLED |
                                               EXIT_POLICY_ADD_DEFAULT,0));
   tt_assert(policy);
 
   //test_streq(policy->string, "accept *:80");
   //test_streq(policy->next->string, "reject *:*");
-  tt_int_op(smartlist_len(policy),OP_EQ, 4);
+  tt_int_op(smartlist_len(policy),OP_EQ, 9);
 
   /* test policy summaries */
   /* check if we properly ignore private IP addresses */
@@ -427,6 +461,10 @@ test_policies_general(void *arg)
   addr_policy_list_free(policy5);
   addr_policy_list_free(policy6);
   addr_policy_list_free(policy7);
+  addr_policy_list_free(policy8);
+  addr_policy_list_free(policy9);
+  addr_policy_list_free(policy10);
+  addr_policy_list_free(policy11);
   tor_free(policy_str);
   if (sm) {
     SMARTLIST_FOREACH(sm, char *, s, tor_free(s));





More information about the tor-commits mailing list