tor-commits
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
September 2015
- 15 participants
- 1411 discussions
commit 60312dc08b30243740e85c2a944874014f682579
Author: teor (Tim Wilson-Brown) <teor2345(a)gmail.com>
Date: Wed Sep 9 23:48:33 2015 +1000
Update comments about ExitPolicy parsing
Fix incomplete and incorrect comments.
Comment changes only.
---
src/common/address.h | 3 +++
src/or/policies.c | 2 +-
src/or/routerparse.c | 10 +++++++---
3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/common/address.h b/src/common/address.h
index cd80615..48a34ce 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -227,6 +227,9 @@ 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
+ * allow *4 and *6 for IPv4 and IPv6 wildcards, respectively;
+ * or does the address * yield IPv4 wildcard address (0). */
#define TAPMP_EXTENDED_STAR 1
int tor_addr_parse_mask_ports(const char *s, unsigned flags,
tor_addr_t *addr_out, maskbits_t *mask_out,
diff --git a/src/or/policies.c b/src/or/policies.c
index 560b8cb..07a3e18 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -152,7 +152,7 @@ policy_expand_unspec(smartlist_t **policy)
}
/**
- * Given a linked list of config lines containing "allow" and "deny"
+ * Given a linked list of config lines containing "accept[6]" and "reject[6]"
* tokens, parse them and append the result to <b>dest</b>. Return -1
* if any tokens are malformed (and don't append any), else return 0.
*
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index c2206f1..d0b2cba 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -3676,10 +3676,14 @@ router_parse_addr_policy_item_from_string,(const char *s, int assume_action))
directory_token_t *tok = NULL;
const char *cp, *eos;
/* Longest possible policy is
- * "accept6 ffff:ffff:..255/ffff:...255:10000-65535",
- * which contains 2 max-length IPv6 addresses, plus 21 characters.
+ * "accept6 ffff:ffff:..255/128:10000-65535",
+ * which contains a max-length IPv6 address, plus 24 characters.
* But note that there can be an arbitrary amount of space between the
- * accept and the address:mask/port element. */
+ * accept and the address:mask/port element.
+ * We don't need to multiply TOR_ADDR_BUF_LEN by 2, as there is only one
+ * IPv6 address. But making the buffer shorter might cause valid long lines,
+ * which parsed in previous versions, to fail to parse in new versions.
+ * (These lines would have to have excessive amounts of whitespace.) */
char line[TOR_ADDR_BUF_LEN*2 + 32];
addr_policy_t *r;
memarea_t *area = NULL;
1
0

[tor/master] Ignore accept6/reject6 IPv4, warn about unexpected rule outcomes
by nickm@torproject.org 16 Sep '15
by nickm@torproject.org 16 Sep '15
16 Sep '15
commit e033d5e90bcb63b68cfac07a4e041dd0ea839573
Author: teor (Tim Wilson-Brown) <teor2345(a)gmail.com>
Date: Fri Sep 11 15:10:54 2015 +1000
Ignore accept6/reject6 IPv4, warn about unexpected rule outcomes
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.
(accept/reject continue to allow both IPv4 and IPv6 addresses in torrcs.)
* a "private" address alias is used on an accept6 or reject6 line.
The line filters both IPv4 and IPv6 private addresses, disregarding
the 6 in accept6/reject6.
When parsing torrc ExitPolicies, we now issue an info-level message:
* 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".
Patch on 2eb7eafc9d78 and a96c0affcb4c (25 Oct 2012),
released in 0.2.4.7-alpha.
---
changes/bug16069-exit-policy-rule6 | 16 +++++
src/common/address.c | 4 ++
src/or/policies.c | 19 +++++-
src/or/routerparse.c | 51 +++++++++++++-
src/or/routerparse.h | 2 +-
src/or/routerset.c | 17 +++--
src/test/test_policy.c | 130 ++++++++++++++++++++++++++++++------
src/test/test_routerset.c | 7 +-
8 files changed, 212 insertions(+), 34 deletions(-)
diff --git a/changes/bug16069-exit-policy-rule6 b/changes/bug16069-exit-policy-rule6
new file mode 100644
index 0000000..5b0560a
--- /dev/null
+++ b/changes/bug16069-exit-policy-rule6
@@ -0,0 +1,16 @@
+ o Minor bug fixes (torrc exit policies):
+ - 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.
+ (accept/reject continue to allow both IPv4 and IPv6 addresses in
+ torrcs.)
+ * a "private" address alias is used on an accept6 or reject6 line.
+ The line filters both IPv4 and IPv6 private addresses, disregarding
+ the 6 in accept6/reject6.
+ - When parsing torrc ExitPolicies, we now issue an info-level message:
+ * 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".
+ Patch on 2eb7eafc9d78 and a96c0affcb4c (25 Oct 2012),
+ released in 0.2.4.7-alpha.
diff --git a/src/common/address.c b/src/common/address.c
index dd33625..597f699 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -690,6 +690,10 @@ tor_addr_parse_mask_ports(const char *s,
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);
} else {
family = AF_INET;
tor_addr_from_ipv4h(addr_out, 0);
diff --git a/src/or/policies.c b/src/or/policies.c
index 07a3e18..e1d7da1 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -167,6 +167,7 @@ parse_addr_policy(config_line_t *cfg, smartlist_t **dest,
smartlist_t *result;
smartlist_t *entries;
addr_policy_t *item;
+ int malformed_list;
int r = 0;
if (!cfg)
@@ -179,12 +180,22 @@ parse_addr_policy(config_line_t *cfg, smartlist_t **dest,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
SMARTLIST_FOREACH_BEGIN(entries, const char *, ent) {
log_debug(LD_CONFIG,"Adding new entry '%s'",ent);
- item = router_parse_addr_policy_item_from_string(ent, assume_action);
+ malformed_list = 0;
+ item = router_parse_addr_policy_item_from_string(ent, assume_action,
+ &malformed_list);
if (item) {
smartlist_add(result, item);
- } else {
- log_warn(LD_CONFIG,"Malformed policy '%s'.", ent);
+ } else if (malformed_list) {
+ /* the error is so severe the entire list should be discarded */
+ log_warn(LD_CONFIG, "Malformed policy '%s'. Discarding entire policy "
+ "list.", ent);
r = -1;
+ } else {
+ /* the error is minor: don't add the item, but keep processing the
+ * rest of the policies in the list */
+ log_debug(LD_CONFIG, "Ignored policy '%s' due to non-fatal error. "
+ "The remainder of the policy list will be used.",
+ ent);
}
} SMARTLIST_FOREACH_END(ent);
SMARTLIST_FOREACH(entries, char *, ent, tor_free(ent));
@@ -568,6 +579,8 @@ cmp_single_addr_policy(addr_policy_t *a, addr_policy_t *b)
return r;
if ((r=((int)a->is_private - (int)b->is_private)))
return r;
+ /* refcnt and is_canonical are irrelevant to equality,
+ * they are hash table implementation details */
if ((r=tor_addr_compare(&a->addr, &b->addr, CMP_EXACT)))
return r;
if ((r=((int)a->maskbits - (int)b->maskbits)))
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index d0b2cba..2f7e50e 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -3666,12 +3666,20 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos)
* assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
* ADDR_POLICY_REJECT) for items that specify no action.
*
+ * Returns NULL on policy errors.
+ *
+ * If there is a policy error, malformed_list is set to true if the entire
+ * policy list should be discarded. Otherwise, it is set to false, and only
+ * this item should be ignored - the rest of the policy list can continue to
+ * be processed and used.
+ *
* The addr_policy_t returned by this function can have its address set to
* AF_UNSPEC for '*'. Use policy_expand_unspec() to turn this into a pair
* of AF_INET and AF_INET6 items.
*/
MOCK_IMPL(addr_policy_t *,
-router_parse_addr_policy_item_from_string,(const char *s, int assume_action))
+router_parse_addr_policy_item_from_string,(const char *s, int assume_action,
+ int *malformed_list))
{
directory_token_t *tok = NULL;
const char *cp, *eos;
@@ -3688,6 +3696,8 @@ router_parse_addr_policy_item_from_string,(const char *s, int assume_action))
addr_policy_t *r;
memarea_t *area = NULL;
+ tor_assert(malformed_list);
+
s = eat_whitespace(s);
if ((*s == '*' || TOR_ISDIGIT(*s)) && assume_action >= 0) {
if (tor_snprintf(line, sizeof(line), "%s %s",
@@ -3714,9 +3724,32 @@ router_parse_addr_policy_item_from_string,(const char *s, int assume_action))
goto err;
}
+ /* Use the extended interpretation of accept/reject *,
+ * expanding it into an IPv4 wildcard and an IPv6 wildcard.
+ * Also permit *4 and *6 for IPv4 and IPv6 only wildcards. */
r = router_parse_addr_policy(tok, TAPMP_EXTENDED_STAR);
+ if (!r) {
+ goto err;
+ }
+
+ /* Ensure that accept6/reject6 fields are followed by IPv6 addresses.
+ * AF_UNSPEC addresses are only permitted on the accept/reject field type.
+ * Unlike descriptors, torrcs exit policy accept/reject can be followed by
+ * either an IPv4 or IPv6 address. */
+ if ((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
+ tor_addr_family(&r->addr) != AF_INET6) {
+ /* This is a non-fatal error, just ignore this one entry. */
+ *malformed_list = 0;
+ log_warn(LD_DIR, "IPv4 address '%s' with accept6/reject6 field type in "
+ "exit policy. Ignoring, but continuing to parse rules. (Use "
+ "accept/reject with IPv4 addresses.)",
+ tok->n_args == 1 ? tok->args[0] : "");
+ return NULL;
+ }
+
goto done;
err:
+ *malformed_list = 1;
r = NULL;
done:
token_clear(tok);
@@ -3733,19 +3766,26 @@ static int
router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
{
addr_policy_t *newe;
+ /* Use the standard interpretation of accept/reject *, an IPv4 wildcard. */
newe = router_parse_addr_policy(tok, 0);
if (!newe)
return -1;
if (! router->exit_policy)
router->exit_policy = smartlist_new();
+ /* Ensure that in descriptors, accept/reject fields are followed by
+ * IPv4 addresses, and accept6/reject6 fields are followed by
+ * IPv6 addresses. Unlike torrcs, descriptor exit policies do not permit
+ * accept/reject followed by IPv6. */
if (((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
tor_addr_family(&newe->addr) == AF_INET)
||
((tok->tp == K_ACCEPT || tok->tp == K_REJECT) &&
tor_addr_family(&newe->addr) == AF_INET6)) {
+ /* There's nothing the user can do about other relays' descriptors,
+ * so we don't provide usage advice here. */
log_warn(LD_DIR, "Mismatch between field type and address type in exit "
- "policy");
+ "policy '%s'. Ignoring.", tok->n_args == 1 ? tok->args[0] : "");
addr_policy_free(newe);
return -1;
}
@@ -3821,6 +3861,13 @@ router_parse_addr_policy_private(directory_token_t *tok)
result.prt_min = port_min;
result.prt_max = port_max;
+ if (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) {
+ log_warn(LD_GENERAL,
+ "'%s' expands into rules which apply to all private IPv4 and "
+ "IPv6 addresses. (Use accept/reject private:* for IPv4 and "
+ "IPv6.)", tok->n_args == 1 ? tok->args[0] : "");
+ }
+
return addr_policy_get_canonical_entry(&result);
}
diff --git a/src/or/routerparse.h b/src/or/routerparse.h
index 85e4b7d..99fd528 100644
--- a/src/or/routerparse.h
+++ b/src/or/routerparse.h
@@ -41,7 +41,7 @@ extrainfo_t *extrainfo_parse_entry_from_string(const char *s, const char *end,
int cache_copy, struct digest_ri_map_t *routermap,
int *can_dl_again_out);
MOCK_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
- (const char *s, int assume_action));
+ (const char *s, int assume_action, int *malformed_list));
version_status_t tor_version_is_obsolete(const char *myversion,
const char *versionlist);
int tor_version_as_new_as(const char *platform, const char *cutoff);
diff --git a/src/or/routerset.c b/src/or/routerset.c
index 9fe5dff..3be55d3 100644
--- a/src/or/routerset.c
+++ b/src/or/routerset.c
@@ -85,10 +85,13 @@ routerset_parse(routerset_t *target, const char *s, const char *description)
int added_countries = 0;
char *countryname;
smartlist_t *list = smartlist_new();
+ int malformed_list;
smartlist_split_string(list, s, ",",
SPLIT_SKIP_SPACE | SPLIT_IGNORE_BLANK, 0);
SMARTLIST_FOREACH_BEGIN(list, char *, nick) {
addr_policy_t *p;
+ /* if it doesn't pass our validation, assume it's malformed */
+ malformed_list = 1;
if (is_legal_hexdigest(nick)) {
char d[DIGEST_LEN];
if (*nick == '$')
@@ -106,15 +109,21 @@ routerset_parse(routerset_t *target, const char *s, const char *description)
added_countries = 1;
} else if ((strchr(nick,'.') || strchr(nick, '*')) &&
(p = router_parse_addr_policy_item_from_string(
- nick, ADDR_POLICY_REJECT))) {
+ nick, ADDR_POLICY_REJECT,
+ &malformed_list))) {
log_debug(LD_CONFIG, "Adding address %s to %s", nick, description);
smartlist_add(target->policies, p);
- } else {
- log_warn(LD_CONFIG, "Entry '%s' in %s is malformed.", nick,
- description);
+ } else if (malformed_list) {
+ log_warn(LD_CONFIG, "Entry '%s' in %s is malformed. Discarding entire"
+ " list.", nick, description);
r = -1;
tor_free(nick);
SMARTLIST_DEL_CURRENT(list, nick);
+ } else {
+ log_notice(LD_CONFIG, "Entry '%s' in %s is ignored. Using the"
+ " remainder of the list.", nick, description);
+ tor_free(nick);
+ SMARTLIST_DEL_CURRENT(list, nick);
}
} SMARTLIST_FOREACH_END(nick);
policy_expand_unspec(&target->policies);
diff --git a/src/test/test_policy.c b/src/test/test_policy.c
index 33f90c7..5e91468 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -84,11 +84,13 @@ test_policies_general(void *arg)
smartlist_t *sm = NULL;
char *policy_str = NULL;
short_policy_t *short_parsed = NULL;
+ int malformed_list = -1;
(void)arg;
policy = smartlist_new();
- p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
tt_int_op(ADDR_POLICY_REJECT,OP_EQ, p->policy_type);
tor_addr_from_ipv4h(&tar, 0xc0a80000u);
@@ -117,60 +119,76 @@ test_policies_general(void *arg)
tt_assert(policy2);
policy3 = smartlist_new();
- p = router_parse_addr_policy_item_from_string("reject *:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject *:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy3, p);
- p = router_parse_addr_policy_item_from_string("accept *:*",-1);
+ p = router_parse_addr_policy_item_from_string("accept *:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy3, p);
policy4 = smartlist_new();
- p = router_parse_addr_policy_item_from_string("accept *:443",-1);
+ p = router_parse_addr_policy_item_from_string("accept *:443", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy4, p);
- p = router_parse_addr_policy_item_from_string("accept *:443",-1);
+ p = router_parse_addr_policy_item_from_string("accept *:443", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy4, p);
policy5 = smartlist_new();
- p = router_parse_addr_policy_item_from_string("reject 0.0.0.0/8:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject 0.0.0.0/8:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("reject 169.254.0.0/16:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject 169.254.0.0/16:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("reject 127.0.0.0/8:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject 127.0.0.0/8:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",
+ -1, &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("reject 10.0.0.0/8:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject 10.0.0.0/8:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("reject 172.16.0.0/12:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject 172.16.0.0/12:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("reject 80.190.250.90:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject 80.190.250.90:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("reject *:1-65534",-1);
+ p = router_parse_addr_policy_item_from_string("reject *:1-65534", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("reject *:65535",-1);
+ p = router_parse_addr_policy_item_from_string("reject *:65535", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
- p = router_parse_addr_policy_item_from_string("accept *:1-65535",-1);
+ p = router_parse_addr_policy_item_from_string("accept *:1-65535", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy5, p);
policy6 = smartlist_new();
- p = router_parse_addr_policy_item_from_string("accept 43.3.0.0/9:*",-1);
+ p = router_parse_addr_policy_item_from_string("accept 43.3.0.0/9:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy6, p);
policy7 = smartlist_new();
- p = router_parse_addr_policy_item_from_string("accept 0.0.0.0/8:*",-1);
+ p = router_parse_addr_policy_item_from_string("accept 0.0.0.0/8:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy7, p);
@@ -297,6 +315,68 @@ test_policies_general(void *arg)
TT_BAD_SHORT_POLICY("accept 1-,3");
TT_BAD_SHORT_POLICY("accept 1-,3");
+ /* Make sure that IPv4 addresses are ignored in accept6/reject6 lines. */
+ p = router_parse_addr_policy_item_from_string("accept6 1.2.3.4:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(!malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("reject6 2.4.6.0/24:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(!malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("accept6 *4:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(!malformed_list);
+
+ /* Make sure malformed policies are detected as such. */
+ p = router_parse_addr_policy_item_from_string("bad_token *4:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("accept6 **:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("accept */15:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("reject6 */:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("accept 127.0.0.1/33:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("accept6 [::1]/129:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("reject 8.8.8.8/-1:*", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("reject 8.8.4.4:10-5", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
+ p = router_parse_addr_policy_item_from_string("reject 1.2.3.4:-1", -1,
+ &malformed_list);
+ tt_assert(p == NULL);
+ tt_assert(malformed_list);
+
/* Test a too-long policy. */
{
int i;
@@ -360,6 +440,7 @@ test_dump_exit_policy_to_string(void *arg)
{
char *ep;
addr_policy_t *policy_entry;
+ int malformed_list = -1;
routerinfo_t *ri = tor_malloc_zero(sizeof(routerinfo_t));
@@ -376,7 +457,8 @@ test_dump_exit_policy_to_string(void *arg)
ri->exit_policy = smartlist_new();
ri->policy_is_reject_star = 0;
- policy_entry = router_parse_addr_policy_item_from_string("accept *:*",-1);
+ policy_entry = router_parse_addr_policy_item_from_string("accept *:*", -1,
+ &malformed_list);
smartlist_add(ri->exit_policy,policy_entry);
@@ -386,7 +468,8 @@ test_dump_exit_policy_to_string(void *arg)
tor_free(ep);
- policy_entry = router_parse_addr_policy_item_from_string("reject *:25",-1);
+ policy_entry = router_parse_addr_policy_item_from_string("reject *:25", -1,
+ &malformed_list);
smartlist_add(ri->exit_policy,policy_entry);
@@ -397,7 +480,8 @@ test_dump_exit_policy_to_string(void *arg)
tor_free(ep);
policy_entry =
- router_parse_addr_policy_item_from_string("reject 8.8.8.8:*",-1);
+ router_parse_addr_policy_item_from_string("reject 8.8.8.8:*", -1,
+ &malformed_list);
smartlist_add(ri->exit_policy,policy_entry);
@@ -407,7 +491,8 @@ test_dump_exit_policy_to_string(void *arg)
tor_free(ep);
policy_entry =
- router_parse_addr_policy_item_from_string("reject6 [FC00::]/7:*",-1);
+ router_parse_addr_policy_item_from_string("reject6 [FC00::]/7:*", -1,
+ &malformed_list);
smartlist_add(ri->exit_policy,policy_entry);
@@ -418,7 +503,8 @@ test_dump_exit_policy_to_string(void *arg)
tor_free(ep);
policy_entry =
- router_parse_addr_policy_item_from_string("accept6 [c000::]/3:*",-1);
+ router_parse_addr_policy_item_from_string("accept6 [c000::]/3:*", -1,
+ &malformed_list);
smartlist_add(ri->exit_policy,policy_entry);
diff --git a/src/test/test_routerset.c b/src/test/test_routerset.c
index 9bd0c12..90dfb28 100644
--- a/src/test/test_routerset.c
+++ b/src/test/test_routerset.c
@@ -430,7 +430,7 @@ NS(test_main)(void *arg)
*/
NS_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
- (const char *s, int assume_action));
+ (const char *s, int assume_action, int *malformed_list));
addr_policy_t *NS(mock_addr_policy);
@@ -457,10 +457,13 @@ NS(test_main)(void *arg)
}
addr_policy_t *
-NS(router_parse_addr_policy_item_from_string)(const char *s, int assume_action)
+NS(router_parse_addr_policy_item_from_string)(const char *s,
+ int assume_action,
+ int *malformed_list)
{
(void)s;
(void)assume_action;
+ (void)malformed_list;
CALLED(router_parse_addr_policy_item_from_string)++;
return NS(mock_addr_policy);
1
0

[tor/master] Add get_interface_address[6]_list for a list of interface IP addresses
by nickm@torproject.org 16 Sep '15
by nickm@torproject.org 16 Sep '15
16 Sep '15
commit 31eb486c4624d1437d982ffdfc1f9d7d83c5ffd6
Author: teor (Tim Wilson-Brown) <teor2345(a)gmail.com>
Date: Tue Sep 15 17:04:18 2015 +1000
Add get_interface_address[6]_list for a list of interface IP addresses
Add get_interface_address[6]_list by refactoring
get_interface_address6. Add unit tests for new and existing functions.
Preparation for ticket 17027. Patch by "teor".
Patch on 42b8fb5a1523 (11 Nov 2007), released in 0.2.0.11-alpha.
---
changes/bug17027-reject-private-all-interfaces | 5 +
src/common/address.c | 107 +++++++++--
src/common/address.h | 28 ++-
src/test/test_address.c | 231 ++++++++++++++++++++++--
4 files changed, 335 insertions(+), 36 deletions(-)
diff --git a/changes/bug17027-reject-private-all-interfaces b/changes/bug17027-reject-private-all-interfaces
new file mode 100644
index 0000000..2801642
--- /dev/null
+++ b/changes/bug17027-reject-private-all-interfaces
@@ -0,0 +1,5 @@
+ o Minor bug fixes (security, exit policies):
+ - Add get_interface_address[6]_list by refactoring
+ get_interface_address6. Add unit tests for new and existing functions.
+ Preparation for ticket 17027. Patch by "teor".
+ Patch on 42b8fb5a1523 (11 Nov 2007), released in 0.2.0.11-alpha.
diff --git a/src/common/address.c b/src/common/address.c
index dd33625..0614256 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -1503,7 +1503,7 @@ get_interface_addresses_raw(int severity)
}
/** Return true iff <b>a</b> is a multicast address. */
-static int
+STATIC int
tor_addr_is_multicast(const tor_addr_t *a)
{
sa_family_t family = tor_addr_family(a);
@@ -1593,27 +1593,26 @@ get_interface_address6_via_udp_socket_hack(int severity,
return r;
}
-/** Set *<b>addr</b> to the IP address (if any) of whatever interface
- * connects to the Internet. This address should only be used in checking
- * whether our address has changed. Return 0 on success, -1 on failure.
+/** Set *<b>addr</b> to an arbitrary IP address (if any) of an interface that
+ * connects to the Internet. Prefer public IP addresses to internal IP
+ * addresses. This address should only be used in checking whether our
+ * address has changed, as it may be an internal IP address. Return 0 on
+ * success, -1 on failure.
+ * Prefer get_interface_address6_list for a list of all addresses on all
+ * interfaces which connect to the Internet.
*/
MOCK_IMPL(int,
get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr))
{
- /* XXX really, this function should yield a smartlist of addresses. */
smartlist_t *addrs;
tor_assert(addr);
- /* Try to do this the smart way if possible. */
- if ((addrs = get_interface_addresses_raw(severity))) {
+ /* Get a list of public or internal IPs in arbitrary order */
+ if ((addrs = get_interface_address6_list(severity, family, 1))) {
int rv = -1;
+ /* Find the first non-internal address, or the last internal address
+ * Ideally, we want the default route, see #12377 for details */
SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a) {
- if (family != AF_UNSPEC && family != tor_addr_family(a))
- continue;
- if (tor_addr_is_loopback(a) ||
- tor_addr_is_multicast(a))
- continue;
-
tor_addr_copy(addr, a);
rv = 0;
@@ -1623,13 +1622,78 @@ get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr))
break;
} SMARTLIST_FOREACH_END(a);
- SMARTLIST_FOREACH(addrs, tor_addr_t *, a, tor_free(a));
- smartlist_free(addrs);
+ free_interface_address6_list(addrs);
return rv;
}
+ return -1;
+}
+
+/** Free a smartlist of IP addresses returned by get_interface_address6_list.
+ */
+void free_interface_address6_list(smartlist_t *addrs) {
+ SMARTLIST_FOREACH(addrs, tor_addr_t *, a, tor_free(a));
+ smartlist_free(addrs);
+}
+
+/** Return a smartlist of the IP addresses of type family from all interfaces
+ * on the server. Excludes loopback and multicast addresses. Only includes
+ * internal addresses if include_internal is true. (Note that a relay behind
+ * NAT may use an internal address to connect to the Internet.)
+ * An empty smartlist means that there are no addresses of the selected type
+ * matching these criteria.
+ * Returns NULL on failure.
+ * Use free_interface_address6_list to free the returned list.
+ */
+MOCK_IMPL(smartlist_t *,get_interface_address6_list,(int severity,
+ sa_family_t family,
+ int include_internal))
+{
+ smartlist_t *addrs;
+ tor_addr_t addr;
+
+ /* Try to do this the smart way if possible. */
+ if ((addrs = get_interface_addresses_raw(severity))) {
+ SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a) {
+ if (family != AF_UNSPEC && family != tor_addr_family(a)){
+ SMARTLIST_DEL_CURRENT(addrs, a);
+ tor_free(a);
+ continue;
+ }
+
+ if (tor_addr_is_loopback(a) ||
+ tor_addr_is_multicast(a)) {
+ SMARTLIST_DEL_CURRENT(addrs, a);
+ tor_free(a);
+ continue;
+ }
+
+ if (!include_internal && tor_addr_is_internal(a, 0)){
+ SMARTLIST_DEL_CURRENT(addrs, a);
+ tor_free(a);
+ continue;
+ }
+ } SMARTLIST_FOREACH_END(a);
+ }
+
+ if (addrs && smartlist_len(addrs) > 0) {
+ return addrs;
+ }
+
+ /* if we removed all entries as unsuitable */
+ if (addrs) {
+ smartlist_free(addrs);
+ }
+
/* Okay, the smart way is out. */
- return get_interface_address6_via_udp_socket_hack(severity,family,addr);
+ get_interface_address6_via_udp_socket_hack(severity,family,&addr);
+ if (!include_internal && tor_addr_is_internal(&addr, 0)) {
+ return smartlist_new();
+ } else {
+ addrs = smartlist_new();
+ smartlist_add(addrs, tor_dup_addr(&addr));
+ return addrs;
+ }
}
/* ======
@@ -1871,10 +1935,13 @@ tor_dup_ip(uint32_t addr)
}
/**
- * Set *<b>addr</b> to the host-order IPv4 address (if any) of whatever
- * interface connects to the Internet. This address should only be used in
- * checking whether our address has changed. Return 0 on success, -1 on
- * failure.
+ * Set *<b>addr</b> to a host-order IPv4 address (if any) of an
+ * interface that connects to the Internet. Prefer public IP addresses to
+ * internal IP addresses. This address should only be used in checking
+ * whether our address has changed, as it may be an internal IPv4 address.
+ * Return 0 on success, -1 on failure.
+ * Prefer get_interface_address_list6 for a list of all IPv4 and IPv6
+ * addresses on all interfaces which connect to the Internet.
*/
MOCK_IMPL(int,
get_interface_address,(int severity, uint32_t *addr))
diff --git a/src/common/address.h b/src/common/address.h
index cd80615..c15dea8 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -15,6 +15,7 @@
#include "orconfig.h"
#include "torint.h"
#include "compat.h"
+#include "container.h"
#ifdef ADDRESS_PRIVATE
@@ -43,7 +44,6 @@
#endif
// TODO win32 specific includes
-#include "container.h"
#endif // ADDRESS_PRIVATE
/** The number of bits from an address to consider while doing a masked
@@ -190,8 +190,13 @@ char *tor_dup_addr(const tor_addr_t *addr) ATTR_MALLOC;
const char *fmt_addr_impl(const tor_addr_t *addr, int decorate);
const char *fmt_addrport(const tor_addr_t *addr, uint16_t port);
const char * fmt_addr32(uint32_t addr);
+
MOCK_DECL(int,get_interface_address6,(int severity, sa_family_t family,
tor_addr_t *addr));
+void free_interface_address6_list(smartlist_t * addrs);
+MOCK_DECL(smartlist_t *,get_interface_address6_list,(int severity,
+ sa_family_t family,
+ int include_internal));
/** Flag to specify how to do a comparison between addresses. In an "exact"
* comparison, addresses are equivalent only if they are in the same family
@@ -269,11 +274,32 @@ int addr_mask_get_bits(uint32_t mask);
int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len);
char *tor_dup_ip(uint32_t addr) ATTR_MALLOC;
MOCK_DECL(int,get_interface_address,(int severity, uint32_t *addr));
+/** Free a smartlist of IP addresses returned by get_interface_address_list.
+ */
+static INLINE void
+free_interface_address_list(smartlist_t *addrs)
+{
+ free_interface_address6_list(addrs);
+}
+/** Return a smartlist of the IPv4 addresses of all interfaces on the server.
+ * Excludes loopback and multicast addresses. Only includes internal addresses
+ * if include_internal is true. (Note that a relay behind NAT may use an
+ * internal address to connect to the Internet.)
+ * An empty smartlist means that there are no IPv4 addresses.
+ * Returns NULL on failure.
+ * Use free_interface_address_list to free the returned list.
+ */
+static INLINE smartlist_t *
+get_interface_address_list(int severity, int include_internal)
+{
+ return get_interface_address6_list(severity, AF_INET, include_internal);
+}
tor_addr_port_t *tor_addr_port_new(const tor_addr_t *addr, uint16_t port);
#ifdef ADDRESS_PRIVATE
STATIC smartlist_t *get_interface_addresses_raw(int severity);
+STATIC int tor_addr_is_multicast(const tor_addr_t *a);
STATIC int get_interface_address6_via_udp_socket_hack(int severity,
sa_family_t family,
tor_addr_t *addr);
diff --git a/src/test/test_address.c b/src/test/test_address.c
index 9d64563..5a41267 100644
--- a/src/test/test_address.c
+++ b/src/test/test_address.c
@@ -74,37 +74,82 @@ sockaddr_in_from_string(const char *ip_str, struct sockaddr_in *out)
}
/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
- * that points to 127.0.0.1. Otherwise, return 0.
+ * that is an IPv4 or IPv6 localhost address. Otherwise, return 0.
*/
static int
smartlist_contains_localhost_tor_addr(smartlist_t *smartlist)
{
- int found_localhost = 0;
+ SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
+ if (tor_addr_is_loopback(tor_addr)) {
+ return 1;
+ }
+ } SMARTLIST_FOREACH_END(tor_addr);
- struct sockaddr_in *sockaddr_localhost;
- struct sockaddr_storage *sockaddr_to_check;
+ return 0;
+}
- sockaddr_localhost = sockaddr_in_from_string("127.0.0.1",NULL);
+/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
+ * that is an IPv4 or IPv6 multicast address. Otherwise, return 0.
+ */
+static int
+smartlist_contains_multicast_tor_addr(smartlist_t *smartlist)
+{
+ SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
+ if (tor_addr_is_multicast(tor_addr)) {
+ return 1;
+ }
+ } SMARTLIST_FOREACH_END(tor_addr);
- sockaddr_to_check = tor_malloc(sizeof(struct sockaddr_in));
+ return 0;
+}
+/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
+ * that is an IPv4 or IPv6 internal address. Otherwise, return 0.
+ */
+static int
+smartlist_contains_internal_tor_addr(smartlist_t *smartlist)
+{
SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
- tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check,
- sizeof(struct sockaddr_in));
+ if (tor_addr_is_internal(tor_addr, 0)) {
+ return 1;
+ }
+ } SMARTLIST_FOREACH_END(tor_addr);
- if (sockaddr_in_are_equal((struct sockaddr_in *)sockaddr_to_check,
- sockaddr_localhost)) {
- found_localhost = 1;
- break;
+ return 0;
+}
+
+/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
+ * that is an IPv4 address. Otherwise, return 0.
+ */
+static int
+smartlist_contains_ipv4_tor_addr(smartlist_t *smartlist)
+{
+ SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
+ if (tor_addr_is_v4(tor_addr)) {
+ return 1;
}
} SMARTLIST_FOREACH_END(tor_addr);
- tor_free(sockaddr_localhost);
- tor_free(sockaddr_to_check);
+ return 0;
+}
- return found_localhost;
+/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
+ * that is an IPv6 address. Otherwise, return 0.
+ */
+static int
+smartlist_contains_ipv6_tor_addr(smartlist_t *smartlist)
+{
+ SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
+ /* Since there's no tor_addr_is_v6, assume all non-v4s are v6 */
+ if (!tor_addr_is_v4(tor_addr)) {
+ return 1;
+ }
+ } SMARTLIST_FOREACH_END(tor_addr);
+
+ return 0;
}
+
#ifdef HAVE_IFADDRS_TO_SMARTLIST
static void
test_address_ifaddrs_to_smartlist(void *arg)
@@ -634,12 +679,168 @@ test_address_udp_socket_trick_blackbox(void *arg)
return;
}
+static void
+test_address_get_if_addrs_list_internal(void *arg)
+{
+ smartlist_t *results = NULL;
+
+ (void)arg;
+
+ results = get_interface_address_list(LOG_ERR, 1);
+
+ tt_assert(results != NULL);
+ /* Assume every system has at least 1 non-local non-multicast IPv4
+ * interface, even if it is an internal one */
+ tt_int_op(smartlist_len(results),>=,1);
+
+ tt_assert(!smartlist_contains_localhost_tor_addr(results));
+ tt_assert(!smartlist_contains_multicast_tor_addr(results));
+ /* The list may or may not contain internal addresses */
+
+ tt_assert(smartlist_contains_ipv4_tor_addr(results));
+ tt_assert(!smartlist_contains_ipv6_tor_addr(results));
+
+done:
+ free_interface_address_list(results);
+ return;
+}
+
+static void
+test_address_get_if_addrs_list_no_internal(void *arg)
+{
+ smartlist_t *results = NULL;
+
+ (void)arg;
+
+ results = get_interface_address_list(LOG_ERR, 0);
+
+ tt_assert(results != NULL);
+ /* Work even on systems with only internal IPv4 addresses */
+ tt_int_op(smartlist_len(results),>=,0);
+
+ tt_assert(!smartlist_contains_localhost_tor_addr(results));
+ tt_assert(!smartlist_contains_multicast_tor_addr(results));
+ tt_assert(!smartlist_contains_internal_tor_addr(results));
+
+ /* The list may or may not contain IPv4 addresses */
+ tt_assert(!smartlist_contains_ipv6_tor_addr(results));
+
+done:
+ free_interface_address_list(results);
+ return;
+}
+
+static void
+test_address_get_if_addrs6_list_internal(void *arg)
+{
+ smartlist_t *results = NULL;
+
+ (void)arg;
+
+ results = get_interface_address6_list(LOG_ERR, AF_INET6, 1);
+
+ tt_assert(results != NULL);
+ /* Work even on systems without IPv6 interfaces */
+ tt_int_op(smartlist_len(results),>=,0);
+
+ tt_assert(!smartlist_contains_localhost_tor_addr(results));
+ tt_assert(!smartlist_contains_multicast_tor_addr(results));
+ /* The list may or may not contain internal addresses */
+
+ tt_assert(!smartlist_contains_ipv4_tor_addr(results));
+ /* The list may or may not contain IPv6 addresses */
+
+done:
+ free_interface_address6_list(results);
+ return;
+}
+
+static void
+test_address_get_if_addrs6_list_no_internal(void *arg)
+{
+ smartlist_t *results = NULL;
+
+ (void)arg;
+
+ results = get_interface_address6_list(LOG_ERR, AF_INET6, 0);
+
+ tt_assert(results != NULL);
+ /* Work even on systems without IPv6 interfaces */
+ tt_int_op(smartlist_len(results),>=,0);
+
+ tt_assert(!smartlist_contains_localhost_tor_addr(results));
+ tt_assert(!smartlist_contains_multicast_tor_addr(results));
+ tt_assert(!smartlist_contains_internal_tor_addr(results));
+
+ tt_assert(!smartlist_contains_ipv4_tor_addr(results));
+ /* The list may or may not contain IPv6 addresses */
+
+done:
+ free_interface_address6_list(results);
+ return;
+}
+
+static void
+test_address_get_if_addrs(void *arg)
+{
+ int rv;
+ uint32_t addr_h = 0;
+ tor_addr_t tor_addr;
+
+ (void)arg;
+
+ rv = get_interface_address(LOG_ERR, &addr_h);
+
+ /* Assume every system has at least 1 non-local non-multicast IPv4
+ * interface, even if it is an internal one */
+ tt_assert(rv == 0);
+ tor_addr_from_ipv4h(&tor_addr, addr_h);
+
+ tt_assert(!tor_addr_is_loopback(&tor_addr));
+ tt_assert(!tor_addr_is_multicast(&tor_addr));
+ /* The address may or may not be an internal address */
+
+ tt_assert(tor_addr_is_v4(&tor_addr));
+
+done:
+ return;
+}
+
+static void
+test_address_get_if_addrs6(void *arg)
+{
+ int rv;
+ tor_addr_t tor_addr;
+
+ (void)arg;
+
+ rv = get_interface_address6(LOG_ERR, AF_INET6, &tor_addr);
+
+ /* Work even on systems without IPv6 interfaces */
+ if (rv == 0) {
+ tt_assert(!tor_addr_is_loopback(&tor_addr));
+ tt_assert(!tor_addr_is_multicast(&tor_addr));
+ /* The address may or may not be an internal address */
+
+ tt_assert(!tor_addr_is_v4(&tor_addr));
+ }
+
+done:
+ return;
+}
+
#define ADDRESS_TEST(name, flags) \
{ #name, test_address_ ## name, flags, NULL, NULL }
struct testcase_t address_tests[] = {
ADDRESS_TEST(udp_socket_trick_whitebox, TT_FORK),
ADDRESS_TEST(udp_socket_trick_blackbox, TT_FORK),
+ ADDRESS_TEST(get_if_addrs_list_internal, 0),
+ ADDRESS_TEST(get_if_addrs_list_no_internal, 0),
+ ADDRESS_TEST(get_if_addrs6_list_internal, 0),
+ ADDRESS_TEST(get_if_addrs6_list_no_internal, 0),
+ ADDRESS_TEST(get_if_addrs, 0),
+ ADDRESS_TEST(get_if_addrs6, 0),
#ifdef HAVE_IFADDRS_TO_SMARTLIST
ADDRESS_TEST(get_if_addrs_ifaddrs, TT_FORK),
ADDRESS_TEST(ifaddrs_to_smartlist, 0),
1
0

[tor/master] Warn about redundant torrc ExitPolicy lines due to accept/reject *:*
by nickm@torproject.org 16 Sep '15
by nickm@torproject.org 16 Sep '15
16 Sep '15
commit 36ad8d8fdc18e9006cd1316deb79b37c77cf2892
Author: teor (Tim Wilson-Brown) <teor2345(a)gmail.com>
Date: Mon Sep 14 21:56:14 2015 +1000
Warn about redundant torrc ExitPolicy lines due to accept/reject *:*
Tor now warns when ExitPolicy lines occur after accept/reject *:*
or variants. These lines are redundant, and were always ignored.
Partial fix for ticket 16069. Patch by "teor".
Patch on 2eb7eafc9d78 and a96c0affcb4c (25 Oct 2012),
released in 0.2.4.7-alpha.
---
changes/bug16069-exit-policy-rule6 | 2 ++
src/or/policies.c | 60 ++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/changes/bug16069-exit-policy-rule6 b/changes/bug16069-exit-policy-rule6
index 5b0560a..5e7b894 100644
--- a/changes/bug16069-exit-policy-rule6
+++ b/changes/bug16069-exit-policy-rule6
@@ -7,6 +7,8 @@
* a "private" address alias is used on an accept6 or reject6 line.
The line filters both IPv4 and IPv6 private addresses, disregarding
the 6 in accept6/reject6.
+ * any ExitPolicy lines occur after accept/reject *:* or variants.
+ These are redundant, and were always ignored.
- When parsing torrc ExitPolicies, we now issue an info-level message:
* when expanding an accept/reject * line to include both IPv4 and IPv6
wildcard addresses.
diff --git a/src/or/policies.c b/src/or/policies.c
index e1d7da1..587245b 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -1013,6 +1013,66 @@ policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest,
}
if (parse_addr_policy(cfg, dest, -1))
return -1;
+
+ /* Before we add the default policy and final rejects, check to see if
+ * there are any lines after accept *:* or reject *:*. These lines have no
+ * effect, and are most likely an error. */
+ int found_final_effective_entry = 0;
+ int first_redundant_entry = 0;
+ for (int i = 0; i < smartlist_len(*dest); ++i) {
+ sa_family_t family;
+ addr_policy_t *p;
+ int found_ipv4_wildcard = 0, found_ipv6_wildcard = 0;
+
+ p = smartlist_get(*dest, i);
+
+ /* Look for accept/reject *[4|6|]:* entires */
+ if (p->prt_min <= 1 && p->prt_max == 65535 && p->maskbits == 0) {
+ family = tor_addr_family(&p->addr);
+ /* accept/reject *:* may have already been expanded into
+ * accept/reject *4:*,accept/reject *6:*
+ * But handle both forms.
+ */
+ if (family == AF_INET || family == AF_UNSPEC) {
+ found_ipv4_wildcard = 1;
+ }
+ if (family == AF_INET6 || family == AF_UNSPEC) {
+ found_ipv6_wildcard = 1;
+ }
+ }
+
+ /* We also find accept *4:*,reject *6:* ; and
+ * accept *4:*,<other policies>,accept *6:* ; and similar.
+ * That's ok, because they make any subsequent entries redundant. */
+ if (found_ipv4_wildcard && found_ipv6_wildcard) {
+ found_final_effective_entry = 1;
+ /* if we're not on the final entry in the list */
+ if (i < smartlist_len(*dest) - 1) {
+ first_redundant_entry = i + 1;
+ }
+ break;
+ }
+ }
+ /* Work out if there are redundant trailing entries in the policy list */
+ if (found_final_effective_entry && first_redundant_entry > 0) {
+ addr_policy_t *p;
+ /* Longest possible policy is
+ * "accept6 ffff:ffff:..255/128:10000-65535",
+ * which contains a max-length IPv6 address, plus 24 characters. */
+ char line[TOR_ADDR_BUF_LEN + 32];
+
+ tor_assert(first_redundant_entry < smartlist_len(*dest));
+ p = smartlist_get(*dest, first_redundant_entry);
+ /* since we've already parsed the policy into an addr_policy_t struct,
+ * we might not log exactly what the user typed in */
+ policy_write_item(line, TOR_ADDR_BUF_LEN + 32, p, 0);
+ log_warn(LD_DIR, "Exit policy '%s' and all following policies are "
+ "redundant, as it follows accept/reject *:* rules for both "
+ "IPv4 and IPv6. They will be removed from the exit policy. (Use "
+ "accept/reject *:* as the last entry in any exit policy.)",
+ line);
+ }
+
if (add_default_policy) {
append_exit_policy_string(dest, DEFAULT_EXIT_POLICY);
} else {
1
0

[tor/master] ExitPolicy accept6/reject6 produces IPv6 wildcard addresses only
by nickm@torproject.org 16 Sep '15
by nickm@torproject.org 16 Sep '15
16 Sep '15
commit d3358a0a05f661f78286d43fcc71d79daa090460
Author: teor (Tim Wilson-Brown) <teor2345(a)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));
1
0

[tor/master] fixup add malformed_list to unit tests from d3358a0a05f6 IPv6 wildcards
by nickm@torproject.org 16 Sep '15
by nickm@torproject.org 16 Sep '15
16 Sep '15
commit 047989ea288fa1e3099f1897a3596abd6f2e8860
Author: teor (Tim Wilson-Brown) <teor2345(a)gmail.com>
Date: Wed Sep 16 00:34:12 2015 +1000
fixup add malformed_list to unit tests from d3358a0a05f6 IPv6 wildcards
The unit tests added in e033d5e90bcb got malformed_list added to
router_parse_addr_policy_item_from_string calls, but unit tests from
subsequent commits didn't get the extra argument until now.
---
src/test/test_policy.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/test/test_policy.c b/src/test/test_policy.c
index 4150b97..e9be9e4 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -208,12 +208,14 @@ test_policies_general(void *arg)
/* accept6 * and reject6 * produce IPv6 wildcards only */
policy10 = smartlist_new();
- p = router_parse_addr_policy_item_from_string("accept6 *:*",-1);
+ p = router_parse_addr_policy_item_from_string("accept6 *:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy10, p);
policy11 = smartlist_new();
- p = router_parse_addr_policy_item_from_string("reject6 *:*",-1);
+ p = router_parse_addr_policy_item_from_string("reject6 *:*", -1,
+ &malformed_list);
tt_assert(p != NULL);
smartlist_add(policy11, p);
1
0

[tor/master] ExitPolicyRejectPrivate rejects local IPv6 address and interface addresses
by nickm@torproject.org 16 Sep '15
by nickm@torproject.org 16 Sep '15
16 Sep '15
commit 098b82c7b2a6bb711e3616eb5b7e7e5e7401f01d
Author: teor (Tim Wilson-Brown) <teor2345(a)gmail.com>
Date: Tue Sep 15 18:34:18 2015 +1000
ExitPolicyRejectPrivate rejects local IPv6 address and interface addresses
ExitPolicyRejectPrivate now rejects more local addresses by default:
* the relay's published IPv6 address (if any), and
* any publicly routable IPv4 or IPv6 addresses on any local interfaces.
This resolves a security issue for IPv6 Exits and multihomed Exits that
trust connections originating from localhost.
Resolves ticket 17027. Patch by "teor".
Patch on 42b8fb5a1523 (11 Nov 2007), released in 0.2.0.11-alpha.
---
changes/bug17027-reject-private-all-interfaces | 7 +-
doc/tor.1.txt | 7 +-
src/common/address.c | 43 ++++----
src/config/torrc.minimal.in-staging | 8 +-
src/config/torrc.sample.in | 8 +-
src/or/policies.c | 125 ++++++++++++++++++++----
src/or/policies.h | 12 +--
src/or/router.c | 2 +-
src/test/test_address.c | 13 ++-
src/test/test_policy.c | 20 +++-
10 files changed, 176 insertions(+), 69 deletions(-)
diff --git a/changes/bug17027-reject-private-all-interfaces b/changes/bug17027-reject-private-all-interfaces
index 2801642..755cd5c 100644
--- a/changes/bug17027-reject-private-all-interfaces
+++ b/changes/bug17027-reject-private-all-interfaces
@@ -1,5 +1,6 @@
o Minor bug fixes (security, exit policies):
- - Add get_interface_address[6]_list by refactoring
- get_interface_address6. Add unit tests for new and existing functions.
- Preparation for ticket 17027. Patch by "teor".
+ - ExitPolicyRejectPrivate rejects more private addresses by default:
+ * the relay's published IPv6 address (if any), and
+ * any publicly routable IPv4 or IPv6 addresses on any local interfaces.
+ Resolves ticket 17027. Patch by "teor".
Patch on 42b8fb5a1523 (11 Nov 2007), released in 0.2.0.11-alpha.
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 89673a8..5ac6164 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -1578,8 +1578,11 @@ is non-zero):
accept *:*
[[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.
+ Reject all private (local) networks, along with your own configured public
+ IPv4 and IPv6 addresses, at the beginning of your exit policy. Also reject
+ any public IPv4 and IPv6 addresses on any interface on the relay. (If
+ IPv6Exit is not set, all IPv6 addresses will be rejected anyway.)
+ See above entry on ExitPolicy.
(Default: 1)
[[IPv6Exit]] **IPv6Exit** **0**|**1**::
diff --git a/src/common/address.c b/src/common/address.c
index 0614256..545865b 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -1605,33 +1605,33 @@ MOCK_IMPL(int,
get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr))
{
smartlist_t *addrs;
+ int rv = -1;
tor_assert(addr);
/* Get a list of public or internal IPs in arbitrary order */
- if ((addrs = get_interface_address6_list(severity, family, 1))) {
- int rv = -1;
- /* Find the first non-internal address, or the last internal address
- * Ideally, we want the default route, see #12377 for details */
- SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a) {
- tor_addr_copy(addr, a);
- rv = 0;
-
- /* If we found a non-internal address, declare success. Otherwise,
- * keep looking. */
- if (!tor_addr_is_internal(a, 0))
- break;
- } SMARTLIST_FOREACH_END(a);
+ addrs = get_interface_address6_list(severity, family, 1);
- free_interface_address6_list(addrs);
- return rv;
- }
+ /* Find the first non-internal address, or the last internal address
+ * Ideally, we want the default route, see #12377 for details */
+ SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a) {
+ tor_addr_copy(addr, a);
+ rv = 0;
- return -1;
+ /* If we found a non-internal address, declare success. Otherwise,
+ * keep looking. */
+ if (!tor_addr_is_internal(a, 0))
+ break;
+ } SMARTLIST_FOREACH_END(a);
+
+ free_interface_address6_list(addrs);
+ return rv;
}
/** Free a smartlist of IP addresses returned by get_interface_address6_list.
*/
-void free_interface_address6_list(smartlist_t *addrs) {
+void
+free_interface_address6_list(smartlist_t *addrs)
+{
SMARTLIST_FOREACH(addrs, tor_addr_t *, a, tor_free(a));
smartlist_free(addrs);
}
@@ -1654,8 +1654,9 @@ MOCK_IMPL(smartlist_t *,get_interface_address6_list,(int severity,
/* Try to do this the smart way if possible. */
if ((addrs = get_interface_addresses_raw(severity))) {
- SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a) {
- if (family != AF_UNSPEC && family != tor_addr_family(a)){
+ SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a)
+ {
+ if (family != AF_UNSPEC && family != tor_addr_family(a)) {
SMARTLIST_DEL_CURRENT(addrs, a);
tor_free(a);
continue;
@@ -1668,7 +1669,7 @@ MOCK_IMPL(smartlist_t *,get_interface_address6_list,(int severity,
continue;
}
- if (!include_internal && tor_addr_is_internal(a, 0)){
+ if (!include_internal && tor_addr_is_internal(a, 0)) {
SMARTLIST_DEL_CURRENT(addrs, a);
tor_free(a);
continue;
diff --git a/src/config/torrc.minimal.in-staging b/src/config/torrc.minimal.in-staging
index d54a559..8ce16bb 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 15 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
@@ -171,8 +171,10 @@
## users will be told that those destinations are down.
##
## For security, by default Tor rejects connections to private (local)
-## networks, including to your public IP address. See the man page entry
-## for ExitPolicyRejectPrivate if you want to allow "exit enclaving".
+## networks, including to the configured public IPv4 and IPv6 addresses,
+## and any public IPv4 and IPv6 addresses on any interface on the relay.
+## 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
diff --git a/src/config/torrc.sample.in b/src/config/torrc.sample.in
index d54a559..8ce16bb 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 15 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
@@ -171,8 +171,10 @@
## users will be told that those destinations are down.
##
## For security, by default Tor rejects connections to private (local)
-## networks, including to your public IP address. See the man page entry
-## for ExitPolicyRejectPrivate if you want to allow "exit enclaving".
+## networks, including to the configured public IPv4 and IPv6 addresses,
+## and any public IPv4 and IPv6 addresses on any interface on the relay.
+## 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
diff --git a/src/or/policies.c b/src/or/policies.c
index 560b8cb..1031fc0 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -67,6 +67,8 @@ static int policies_parse_exit_policy_internal(config_line_t *cfg,
int ipv6_exit,
int rejectprivate,
uint32_t local_address,
+ tor_addr_t *ipv6_local_address,
+ int reject_interface_addresses,
int add_default_policy);
/** Replace all "private" entries in *<b>policy</b> with their expanded
@@ -430,7 +432,7 @@ validate_addr_policies(const or_options_t *options, char **msg)
smartlist_t *addr_policy=NULL;
*msg = NULL;
- if (policies_parse_exit_policy_from_options(options,0,&addr_policy)) {
+ if (policies_parse_exit_policy_from_options(options,0,NULL,0,&addr_policy)) {
REJECT("Error in ExitPolicy entry.");
}
@@ -969,12 +971,24 @@ exit_policy_remove_redundancies(smartlist_t *dest)
"reject *:563,reject *:1214,reject *:4661-4666," \
"reject *:6346-6429,reject *:6699,reject *:6881-6999,accept *:*"
-/** Parse the exit policy <b>cfg</b> into the linked list *<b>dest</b>. If
- * cfg doesn't end in an absolute accept or reject and if
+/** Parse the exit policy <b>cfg</b> into the linked list *<b>dest</b>.
+ *
+ * If <b>ipv6_exit</b> is true, prepend "reject *6:*" to the policy.
+ *
+ * If <b>rejectprivate</b> is true:
+ * - prepend "reject private:*" to the policy.
+ * - if local_address is non-zero, treat it as a host-order IPv4 address,
+ * and prepend an entry that rejects it as a destination.
+ * - if ipv6_local_address is non-NULL, prepend an entry that rejects it as
+ * a destination.
+ * - if reject_interface_addresses is true, prepend entries that reject each
+ * public IPv4 and IPv6 address of each interface on this machine.
+ *
+ * If cfg doesn't end in an absolute accept or reject and if
* <b>add_default_policy</b> is true, add the default exit
- * 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.
+ * policy afterwards.
+ *
+ * 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,
@@ -985,18 +999,73 @@ policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest,
int ipv6_exit,
int rejectprivate,
uint32_t local_address,
+ tor_addr_t *ipv6_local_address,
+ int reject_interface_addresses,
int add_default_policy)
{
if (!ipv6_exit) {
append_exit_policy_string(dest, "reject *6:*");
}
if (rejectprivate) {
+ /* Reject IPv4 and IPv6 reserved private netblocks */
append_exit_policy_string(dest, "reject private:*");
+ /* Reject our local IPv4 address */
if (local_address) {
char buf[POLICY_BUF_LEN];
tor_snprintf(buf, sizeof(buf), "reject %s:*", fmt_addr32(local_address));
append_exit_policy_string(dest, buf);
}
+ /* Reject our local IPv6 address */
+ if (ipv6_exit && ipv6_local_address != NULL) {
+ if (tor_addr_is_v4(ipv6_local_address)) {
+ log_warn(LD_CONFIG, "IPv4 address '%s' provided as our IPv6 local "
+ "address", fmt_addr(ipv6_local_address));
+ } else {
+ char buf6[POLICY_BUF_LEN];
+ tor_snprintf(buf6, sizeof(buf6), "reject %s:*",
+ fmt_addr(ipv6_local_address));
+ append_exit_policy_string(dest, buf6);
+ }
+ }
+ /* Reject local addresses from public netblocks on any interface,
+ * but don't reject our published addresses twice */
+ if (reject_interface_addresses) {
+ smartlist_t *public_addresses = NULL;
+ char bufif[POLICY_BUF_LEN];
+
+ /* Reject public IPv4 addresses on any interface,
+ * but don't reject our published IPv4 address twice */
+ public_addresses = get_interface_address6_list(LOG_INFO, AF_INET, 0);
+ SMARTLIST_FOREACH_BEGIN(public_addresses, tor_addr_t *, a) {
+ if (!tor_addr_eq_ipv4h(a, local_address)) {
+ tor_snprintf(bufif, sizeof(bufif), "reject %s:*",
+ fmt_addr(a));
+ append_exit_policy_string(dest, bufif);
+ log_info(LD_CONFIG, "Adding a reject ExitPolicy '%s' for a local "
+ "interface's public IPv4 address", bufif);
+ }
+ } SMARTLIST_FOREACH_END(a);
+ free_interface_address6_list(public_addresses);
+
+ if (ipv6_exit) {
+ /* Reject public IPv6 addresses on any interface,
+ * but don't reject our published IPv6 address (if any) twice */
+ public_addresses = get_interface_address6_list(LOG_INFO, AF_INET6, 0);
+ SMARTLIST_FOREACH_BEGIN(public_addresses, tor_addr_t *, a) {
+ /* if we don't have an IPv6 local address, we won't have rejected
+ * it above. This could happen if a future release does IPv6
+ * autodiscovery, and we are waiting to discover our external IPv6
+ * address */
+ if (ipv6_local_address == NULL
+ || !tor_addr_eq(ipv6_local_address, a)) {
+ tor_snprintf(bufif, sizeof(bufif), "reject6 %s:*",
+ fmt_addr(a));
+ append_exit_policy_string(dest, bufif);
+ }
+ } SMARTLIST_FOREACH_END(a);
+ free_interface_address6_list(public_addresses);
+ }
+ }
}
if (parse_addr_policy(cfg, dest, -1))
return -1;
@@ -1013,20 +1082,28 @@ policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest,
/** Parse exit policy in <b>cfg</b> into <b>dest</b> smartlist.
*
- * Add entry that rejects all IPv6 destinations unless
+ * Prepend an entry that rejects all IPv6 destinations unless
* <b>EXIT_POLICY_IPV6_ENABLED</b> bit is set in <b>options</b> bitmask.
*
- * If <b>EXIT_POLICY_REJECT_PRIVATE</b> bit is set in <b>options</b>,
- * do add entry that rejects all destinations in private subnetwork
- * Tor is running in.
+ * If <b>EXIT_POLICY_REJECT_PRIVATE</b> bit is set in <b>options</b>:
+ * - prepend an entry that rejects all destinations in all netblocks
+ * reserved for private use.
+ * - if local_address is non-zero, treat it as a host-order IPv4 address,
+ * and prepend an entry that rejects it as a destination.
+ * - if ipv6_local_address is non-NULL, prepend an entry that rejects it as
+ * a destination.
+ * - if reject_interface_addresses is true, prepend entries that reject each
+ * public IPv4 and IPv6 address of each interface on this machine.
*
- * Respectively, if <b>EXIT_POLICY_ADD_DEFAULT</b> bit is set, add
+ * If <b>EXIT_POLICY_ADD_DEFAULT</b> bit is set in <b>options</b>, append
* default exit policy entries to <b>result</b> smartlist.
*/
int
policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
exit_policy_parser_cfg_t options,
- uint32_t local_address)
+ uint32_t local_address,
+ tor_addr_t *ipv6_local_address,
+ int reject_interface_addresses)
{
int ipv6_enabled = (options & EXIT_POLICY_IPV6_ENABLED) ? 1 : 0;
int reject_private = (options & EXIT_POLICY_REJECT_PRIVATE) ? 1 : 0;
@@ -1035,19 +1112,27 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
return policies_parse_exit_policy_internal(cfg,dest,ipv6_enabled,
reject_private,
local_address,
+ ipv6_local_address,
+ reject_interface_addresses,
add_default);
}
/** Parse <b>ExitPolicy</b> member of <b>or_options</b> into <b>result</b>
* smartlist.
- * If <b>or_options->IPv6Exit</b> is false, add an entry that
+ * If <b>or_options->IPv6Exit</b> is false, prepend an entry that
* rejects all IPv6 destinations.
*
- * If <b>or_options->ExitPolicyRejectPrivate</b> is true, add entry that
- * rejects all destinations in the private subnetwork of machine Tor
- * instance is running in.
+ * If <b>or_options->ExitPolicyRejectPrivate</b> is true:
+ * - prepend an entry that rejects all destinations in all netblocks reserved
+ * for private use.
+ * - if local_address is non-zero, treat it as a host-order IPv4 address, and
+ * prepend an entry that rejects it as a destination.
+ * - if ipv6_local_address is non-NULL, prepend an entry that rejects it as a
+ * destination.
+ * - if reject_interface_addresses is true, prepend entries that reject each
+ * public IPv4 and IPv6 address of each interface on this machine.
*
- * If <b>or_options->BridgeRelay</b> is false, add entries of default
+ * If <b>or_options->BridgeRelay</b> is false, append entries of default
* Tor exit policy into <b>result</b> smartlist.
*
* If or_options->ExitRelay is false, then make our exit policy into
@@ -1056,6 +1141,8 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
int
policies_parse_exit_policy_from_options(const or_options_t *or_options,
uint32_t local_address,
+ tor_addr_t *ipv6_local_address,
+ int reject_interface_addresses,
smartlist_t **result)
{
exit_policy_parser_cfg_t parser_cfg = 0;
@@ -1079,7 +1166,9 @@ policies_parse_exit_policy_from_options(const or_options_t *or_options,
}
return policies_parse_exit_policy(or_options->ExitPolicy,result,
- parser_cfg,local_address);
+ parser_cfg,local_address,
+ ipv6_local_address,
+ reject_interface_addresses);
}
/** Add "reject *:*" to the end of the policy in *<b>dest</b>, allocating
diff --git a/src/or/policies.h b/src/or/policies.h
index 0225b57..f200d7b 100644
--- a/src/or/policies.h
+++ b/src/or/policies.h
@@ -48,18 +48,16 @@ MOCK_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy,
addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr,
uint16_t port, const node_t *node);
-/*
-int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
- int ipv6exit,
- int rejectprivate, uint32_t local_address,
- int add_default_policy);
-*/
int policies_parse_exit_policy_from_options(const or_options_t *or_options,
uint32_t local_address,
+ tor_addr_t *ipv6_local_address,
+ int reject_interface_addresses,
smartlist_t **result);
int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
exit_policy_parser_cfg_t options,
- uint32_t local_address);
+ uint32_t local_address,
+ tor_addr_t *ipv6_local_address,
+ int reject_interface_addresses);
void policies_exit_policy_append_reject_star(smartlist_t **dest);
void addr_policy_append_reject_addr(smartlist_t **dest,
const tor_addr_t *addr);
diff --git a/src/or/router.c b/src/or/router.c
index 03973ae..8fdad9a 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -1922,7 +1922,7 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e)
/* DNS is screwed up; don't claim to be an exit. */
policies_exit_policy_append_reject_star(&ri->exit_policy);
} else {
- policies_parse_exit_policy_from_options(options,ri->addr,
+ policies_parse_exit_policy_from_options(options,ri->addr,&ri->ipv6_addr,1,
&ri->exit_policy);
}
ri->policy_is_reject_star =
diff --git a/src/test/test_address.c b/src/test/test_address.c
index 5a41267..72742df 100644
--- a/src/test/test_address.c
+++ b/src/test/test_address.c
@@ -149,7 +149,6 @@ smartlist_contains_ipv6_tor_addr(smartlist_t *smartlist)
return 0;
}
-
#ifdef HAVE_IFADDRS_TO_SMARTLIST
static void
test_address_ifaddrs_to_smartlist(void *arg)
@@ -700,7 +699,7 @@ test_address_get_if_addrs_list_internal(void *arg)
tt_assert(smartlist_contains_ipv4_tor_addr(results));
tt_assert(!smartlist_contains_ipv6_tor_addr(results));
-done:
+ done:
free_interface_address_list(results);
return;
}
@@ -725,7 +724,7 @@ test_address_get_if_addrs_list_no_internal(void *arg)
/* The list may or may not contain IPv4 addresses */
tt_assert(!smartlist_contains_ipv6_tor_addr(results));
-done:
+ done:
free_interface_address_list(results);
return;
}
@@ -750,7 +749,7 @@ test_address_get_if_addrs6_list_internal(void *arg)
tt_assert(!smartlist_contains_ipv4_tor_addr(results));
/* The list may or may not contain IPv6 addresses */
-done:
+ done:
free_interface_address6_list(results);
return;
}
@@ -775,7 +774,7 @@ test_address_get_if_addrs6_list_no_internal(void *arg)
tt_assert(!smartlist_contains_ipv4_tor_addr(results));
/* The list may or may not contain IPv6 addresses */
-done:
+ done:
free_interface_address6_list(results);
return;
}
@@ -802,7 +801,7 @@ test_address_get_if_addrs(void *arg)
tt_assert(tor_addr_is_v4(&tor_addr));
-done:
+ done:
return;
}
@@ -825,7 +824,7 @@ test_address_get_if_addrs6(void *arg)
tt_assert(!tor_addr_is_v4(&tor_addr));
}
-done:
+ done:
return;
}
diff --git a/src/test/test_policy.c b/src/test/test_policy.c
index 33f90c7..d7d3cf0 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -49,7 +49,7 @@ test_policy_summary_helper(const char *policy_str,
r = policies_parse_exit_policy(&line, &policy,
EXIT_POLICY_IPV6_ENABLED |
- EXIT_POLICY_ADD_DEFAULT ,0);
+ EXIT_POLICY_ADD_DEFAULT, 0, NULL, 0);
tt_int_op(r,OP_EQ, 0);
summary = policy_summarize(policy, AF_INET);
@@ -77,7 +77,7 @@ 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, *policy12 = NULL;
addr_policy_t *p;
tor_addr_t tar;
config_line_t line;
@@ -112,10 +112,20 @@ test_policies_general(void *arg)
tt_int_op(0, OP_EQ, policies_parse_exit_policy(NULL, &policy2,
EXIT_POLICY_IPV6_ENABLED |
EXIT_POLICY_REJECT_PRIVATE |
- EXIT_POLICY_ADD_DEFAULT, 0));
+ EXIT_POLICY_ADD_DEFAULT, 0,
+ NULL, 0));
tt_assert(policy2);
+ tor_addr_parse(&tar, "[2000::1234]");
+ tt_int_op(0, OP_EQ, policies_parse_exit_policy(NULL, &policy12,
+ EXIT_POLICY_IPV6_ENABLED |
+ EXIT_POLICY_REJECT_PRIVATE |
+ EXIT_POLICY_ADD_DEFAULT,
+ 0x0306090cu, &tar, 1));
+
+ tt_assert(policy12);
+
policy3 = smartlist_new();
p = router_parse_addr_policy_item_from_string("reject *:*",-1);
tt_assert(p != NULL);
@@ -202,7 +212,8 @@ test_policies_general(void *arg)
line.next = NULL;
tt_int_op(0, OP_EQ, policies_parse_exit_policy(&line,&policy,
EXIT_POLICY_IPV6_ENABLED |
- EXIT_POLICY_ADD_DEFAULT,0));
+ EXIT_POLICY_ADD_DEFAULT, 0,
+ NULL, 0));
tt_assert(policy);
//test_streq(policy->string, "accept *:80");
@@ -347,6 +358,7 @@ test_policies_general(void *arg)
addr_policy_list_free(policy5);
addr_policy_list_free(policy6);
addr_policy_list_free(policy7);
+ addr_policy_list_free(policy12);
tor_free(policy_str);
if (sm) {
SMARTLIST_FOREACH(sm, char *, s, tor_free(s));
1
0

[tor/master] Log an info-level message for each IP blocked by ExitPolicyRejectPrivate
by nickm@torproject.org 16 Sep '15
by nickm@torproject.org 16 Sep '15
16 Sep '15
commit eb1759e63cccc9fb870dfb2f87b21ce1e6d4df2d
Author: teor (Tim Wilson-Brown) <teor2345(a)gmail.com>
Date: Tue Sep 15 18:57:00 2015 +1000
Log an info-level message for each IP blocked by ExitPolicyRejectPrivate
Log an info-level message containing the reject line added to the
exit policy for each local IP address blocked by ExitPolicyRejectPrivate:
- Published IPv4 and IPv6 addresses
- Publicly routable IPv4 and IPv6 interface addresses
---
src/or/policies.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/or/policies.c b/src/or/policies.c
index 1031fc0..641b109 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -1014,6 +1014,8 @@ policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest,
char buf[POLICY_BUF_LEN];
tor_snprintf(buf, sizeof(buf), "reject %s:*", fmt_addr32(local_address));
append_exit_policy_string(dest, buf);
+ log_info(LD_CONFIG, "Adding a reject ExitPolicy '%s' for our published "
+ "IPv4 address", buf);
}
/* Reject our local IPv6 address */
if (ipv6_exit && ipv6_local_address != NULL) {
@@ -1025,6 +1027,8 @@ policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest,
tor_snprintf(buf6, sizeof(buf6), "reject %s:*",
fmt_addr(ipv6_local_address));
append_exit_policy_string(dest, buf6);
+ log_info(LD_CONFIG, "Adding a reject ExitPolicy '%s' for our "
+ "published IPv6 address", buf6);
}
}
/* Reject local addresses from public netblocks on any interface,
@@ -1061,6 +1065,8 @@ policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest,
tor_snprintf(bufif, sizeof(bufif), "reject6 %s:*",
fmt_addr(a));
append_exit_policy_string(dest, bufif);
+ log_info(LD_CONFIG, "Adding a reject ExitPolicy '%s' for a local "
+ "interface's public IPv6 address", bufif);
}
} SMARTLIST_FOREACH_END(a);
free_interface_address6_list(public_addresses);
1
0

[tor/master] fixup Clarify ambiguous log message in router_add_exit_policy
by nickm@torproject.org 16 Sep '15
by nickm@torproject.org 16 Sep '15
16 Sep '15
commit fd85f2cd706fe86499962f2364f99daa220186a8
Author: teor (Tim Wilson-Brown) <teor2345(a)gmail.com>
Date: Wed Sep 16 03:59:30 2015 +1000
fixup Clarify ambiguous log message in router_add_exit_policy
---
src/or/routerparse.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 8e56d16..17c46ac 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -3785,7 +3785,8 @@ router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
/* There's nothing the user can do about other relays' descriptors,
* so we don't provide usage advice here. */
log_warn(LD_DIR, "Mismatch between field type and address type in exit "
- "policy '%s'. Ignoring.", tok->n_args == 1 ? tok->args[0] : "");
+ "policy '%s'. Discarding entire router descriptor.",
+ tok->n_args == 1 ? tok->args[0] : "");
addr_policy_free(newe);
return -1;
}
1
0

[tor/master] fixup Only set TAPMP_STAR_IPV6_ONLY if TAPMP_EXTENDED_STAR is set
by nickm@torproject.org 16 Sep '15
by nickm@torproject.org 16 Sep '15
16 Sep '15
commit ab6f93caa719c2b2571b771087efba53d3d51bbf
Author: teor (Tim Wilson-Brown) <teor2345(a)gmail.com>
Date: Wed Sep 16 03:58:06 2015 +1000
fixup Only set TAPMP_STAR_IPV6_ONLY if TAPMP_EXTENDED_STAR is set
Also fix a comment.
---
src/or/routerparse.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 7bb18ec..8e56d16 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -3795,8 +3795,11 @@ router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
return 0;
}
-/** Given a K_ACCEPT or K_REJECT token and a router, create and return
- * a new exit_policy_t corresponding to the token. */
+/** Given a K_ACCEPT[6] or K_REJECT[6] token and a router, create and return
+ * a new exit_policy_t corresponding to the token. If TAPMP_EXTENDED_STAR
+ * is set in fmt_flags, K_ACCEPT6 and K_REJECT6 tokens followed by *
+ * expand to IPv6-only policies, otherwise they expand to IPv4 and IPv6
+ * policies */
static addr_policy_t *
router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags)
{
@@ -3822,7 +3825,8 @@ router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags)
/* 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) {
+ if ((fmt_flags & TAPMP_EXTENDED_STAR)
+ && (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6)) {
fmt_flags |= TAPMP_STAR_IPV6_ONLY;
}
1
0