aboutsummaryrefslogtreecommitdiff
path: root/src/or/policies.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2012-10-24 15:03:29 -0400
committerNick Mathewson <nickm@torproject.org>2012-11-14 23:16:21 -0500
commita96c0affcb4cda1a2e0d83d123993d10efc6e396 (patch)
tree179be96049286cae1b9b1aa4b633f60da2c29023 /src/or/policies.c
parent2eb7eafc9d789cb5063dd36021412434b656bf75 (diff)
downloadtor-a96c0affcb4cda1a2e0d83d123993d10efc6e396.tar.gz
tor-a96c0affcb4cda1a2e0d83d123993d10efc6e396.zip
Better policy support for IPv6
Now, "accept *:80" means "accept all addresses on port 80", and not just IPv4. For just v4, say "accept *4:80"; for just v6 say "accept *6:80". We can parse these policies from torrc just fine, and we should be successfully keeping them out of descriptors for now. We also now include appropriate IPv6 addresses in "reject private:*"
Diffstat (limited to 'src/or/policies.c')
-rw-r--r--src/or/policies.c135
1 files changed, 110 insertions, 25 deletions
diff --git a/src/or/policies.c b/src/or/policies.c
index 442377b1c5..8367446ff2 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -59,8 +59,10 @@ typedef struct policy_summary_item_t {
static const char *private_nets[] = {
"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",
- // "fc00::/7", "fe80::/10", "fec0::/10", "::/127",
- NULL };
+ "[::]/8",
+ "[fc00::]/7", "[fe80::]/10", "[fec0::]/10", "[ff00::]/8", "[::]/127",
+ NULL
+};
/** Replace all "private" entries in *<b>policy</b> with their expanded
* equivalents. */
@@ -101,6 +103,49 @@ policy_expand_private(smartlist_t **policy)
*policy = tmp;
}
+/** Expand each of the AF_UNSPEC elements in *<b>policy</b> (which indicate
+ * protocol-neutral wildcards) into a pair of wildcard elements: one IPv4-
+ * specific and one IPv6-specific. */
+void
+policy_expand_unspec(smartlist_t **policy)
+{
+ smartlist_t *tmp;
+ if (!*policy)
+ return;
+
+ tmp = smartlist_new();
+ SMARTLIST_FOREACH_BEGIN(*policy, addr_policy_t *, p) {
+ sa_family_t family = tor_addr_family(&p->addr);
+ if (family == AF_INET6 || family == AF_INET || p->is_private) {
+ smartlist_add(tmp, p);
+ } else if (family == AF_UNSPEC) {
+ addr_policy_t newpolicy_ipv4;
+ addr_policy_t newpolicy_ipv6;
+ memcpy(&newpolicy_ipv4, p, sizeof(addr_policy_t));
+ memcpy(&newpolicy_ipv6, p, sizeof(addr_policy_t));
+ newpolicy_ipv4.is_canonical = 0;
+ newpolicy_ipv6.is_canonical = 0;
+ if (p->maskbits != 0) {
+ log_warn(LD_BUG, "AF_UNSPEC policy with maskbits==%d", p->maskbits);
+ newpolicy_ipv4.maskbits = 0;
+ newpolicy_ipv6.maskbits = 0;
+ }
+ tor_addr_from_ipv4h(&newpolicy_ipv4.addr, 0);
+ tor_addr_from_ipv6_bytes(&newpolicy_ipv6.addr,
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
+ smartlist_add(tmp, addr_policy_get_canonical_entry(&newpolicy_ipv4));
+ smartlist_add(tmp, addr_policy_get_canonical_entry(&newpolicy_ipv6));
+ addr_policy_free(p);
+ } else {
+ log_warn(LD_BUG, "Funny-looking address policy with family %d", family);
+ smartlist_add(tmp, p);
+ }
+ } SMARTLIST_FOREACH_END(p);
+
+ smartlist_free(*policy);
+ *policy = tmp;
+}
+
/**
* Given a linked list of config lines containing "allow" and "deny"
* tokens, parse them and append the result to <b>dest</b>. Return -1
@@ -145,6 +190,7 @@ parse_addr_policy(config_line_t *cfg, smartlist_t **dest,
addr_policy_list_free(result);
} else {
policy_expand_private(&result);
+ policy_expand_unspec(&result);
if (*dest) {
smartlist_add_all(*dest, result);
@@ -735,6 +781,10 @@ compare_tor_addr_to_addr_policy(const tor_addr_t *addr, uint16_t port,
static int
addr_policy_covers(addr_policy_t *a, addr_policy_t *b)
{
+ if (tor_addr_family(&a->addr) != tor_addr_family(&b->addr)) {
+ /* You can't cover a different family. */
+ return 0;
+ }
/* We can ignore accept/reject, since "accept *:80, reject *:80" reduces
* to "accept *:80". */
if (a->maskbits > b->maskbits) {
@@ -790,20 +840,32 @@ append_exit_policy_string(smartlist_t **policy, const char *more)
static void
exit_policy_remove_redundancies(smartlist_t *dest)
{
- addr_policy_t *ap, *tmp, *victim;
+ addr_policy_t *ap, *tmp;
int i, j;
- /* Step one: find a *:* entry and cut off everything after it. */
- for (i = 0; i < smartlist_len(dest); ++i) {
- ap = smartlist_get(dest, i);
- if (ap->maskbits == 0 && ap->prt_min <= 1 && ap->prt_max >= 65535) {
- /* This is a catch-all line -- later lines are unreachable. */
- while (i+1 < smartlist_len(dest)) {
- victim = smartlist_get(dest, i+1);
- smartlist_del(dest, i+1);
- addr_policy_free(victim);
+ /* Step one: kill every ipv4 thing after *4:*, every IPv6 thing after *6:*
+ */
+ {
+ int kill_v4=0, kill_v6=0;
+ for (i = 0; i < smartlist_len(dest); ++i) {
+ sa_family_t family;
+ ap = smartlist_get(dest, i);
+ family = tor_addr_family(&ap->addr);
+ if ((family == AF_INET && kill_v4) ||
+ (family == AF_INET6 && kill_v6)) {
+ smartlist_del_keeporder(dest, i--);
+ addr_policy_free(ap);
+ continue;
+ }
+
+ if (ap->maskbits == 0 && ap->prt_min <= 1 && ap->prt_max >= 65535) {
+ /* This is a catch-all line -- later lines are unreachable. */
+ if (family == AF_INET) {
+ kill_v4 = 1;
+ } else if (family == AF_INET6) {
+ kill_v6 = 1;
+ }
}
- break;
}
}
@@ -869,6 +931,10 @@ exit_policy_remove_redundancies(smartlist_t *dest)
* policy afterwards. If <b>rejectprivate</b> is true, prepend
* "reject private:*" to the policy. Return -1 if we can't parse cfg,
* else return 0.
+ *
+ * This function is used to parse the exit policy from our torrc. For
+ * the functions used to parse the exit policy from a router descriptor,
+ * see router_add_exit_policy.
*/
int
policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
@@ -885,10 +951,12 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
}
if (parse_addr_policy(cfg, dest, -1))
return -1;
- if (add_default_policy)
+ if (add_default_policy) {
append_exit_policy_string(dest, DEFAULT_EXIT_POLICY);
- else
- append_exit_policy_string(dest, "reject *:*");
+ } else {
+ append_exit_policy_string(dest, "reject *4:*");
+ append_exit_policy_string(dest, "reject *6:*");
+ }
exit_policy_remove_redundancies(*dest);
return 0;
@@ -899,7 +967,8 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
void
policies_exit_policy_append_reject_star(smartlist_t **dest)
{
- append_exit_policy_string(dest, "reject *:*");
+ append_exit_policy_string(dest, "reject *4:*");
+ append_exit_policy_string(dest, "reject *6:*");
}
/** Replace the exit policy of <b>node</b> with reject *:* */
@@ -1001,17 +1070,26 @@ policy_write_item(char *buf, size_t buflen, addr_policy_t *policy,
const char *addrpart;
int result;
const int is_accept = policy->policy_type == ADDR_POLICY_ACCEPT;
- const int is_ip6 = tor_addr_family(&policy->addr) == AF_INET6;
+ const sa_family_t family = tor_addr_family(&policy->addr);
+ const int is_ip6 = (family == AF_INET6);
tor_addr_to_str(addrbuf, &policy->addr, sizeof(addrbuf), 1);
/* write accept/reject 1.2.3.4 */
- if (policy->is_private)
+ if (policy->is_private) {
addrpart = "private";
- else if (policy->maskbits == 0)
- addrpart = "*";
- else
+ } else if (policy->maskbits == 0) {
+ if (format_for_desc)
+ addrpart = "*";
+ else if (family == AF_INET6)
+ addrpart = "*6";
+ else if (family == AF_INET)
+ addrpart = "*4";
+ else
+ addrpart = "*";
+ } else {
addrpart = addrbuf;
+ }
result = tor_snprintf(buf, buflen, "%s%s %s",
is_accept ? "accept" : "reject",
@@ -1220,7 +1298,7 @@ policy_summary_add_item(smartlist_t *summary, addr_policy_t *p)
* is an exception to the shorter-representation-wins rule).
*/
char *
-policy_summarize(smartlist_t *policy)
+policy_summarize(smartlist_t *policy, sa_family_t family)
{
smartlist_t *summary = policy_summary_create();
smartlist_t *accepts, *rejects;
@@ -1232,9 +1310,16 @@ policy_summarize(smartlist_t *policy)
tor_assert(policy);
/* Create the summary list */
- SMARTLIST_FOREACH(policy, addr_policy_t *, p, {
+ SMARTLIST_FOREACH_BEGIN(policy, addr_policy_t *, p) {
+ sa_family_t f = tor_addr_family(&p->addr);
+ if (f != AF_INET && f != AF_INET6) {
+ log_warn(LD_BUG, "Weird family when summarizing address policy");
+ }
+ if (f != family)
+ continue;
+ /* XXXX-ipv6 More family work is needed */
policy_summary_add_item(summary, p);
- });
+ } SMARTLIST_FOREACH_END(p);
/* Now create two lists of strings, one for accepted and one
* for rejected ports. We take care to merge ranges so that