diff options
author | Roger Dingledine <arma@torproject.org> | 2012-10-23 17:26:21 -0400 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2012-10-23 17:26:21 -0400 |
commit | 36801ba3c0c6a08e138cb09ecd7720a0ff711483 (patch) | |
tree | 079a9c0a3041b40cd25aa2b734529187a4db1084 | |
parent | 3a2b86ef5d576e55defb3a9a1e37bee48b7b3d6a (diff) | |
parent | 2ecee3fce2179c6fe9f9c748522e417b887ee021 (diff) | |
download | tor-36801ba3c0c6a08e138cb09ecd7720a0ff711483.tar.gz tor-36801ba3c0c6a08e138cb09ecd7720a0ff711483.zip |
Merge branch 'maint-0.2.3' into release-0.2.3
-rw-r--r-- | changes/bug7190 | 6 | ||||
-rw-r--r-- | changes/bug7192 | 10 | ||||
-rw-r--r-- | src/or/policies.c | 46 | ||||
-rw-r--r-- | src/or/policies.h | 1 | ||||
-rw-r--r-- | src/test/test.c | 66 |
5 files changed, 121 insertions, 8 deletions
diff --git a/changes/bug7190 b/changes/bug7190 new file mode 100644 index 0000000000..1607f79442 --- /dev/null +++ b/changes/bug7190 @@ -0,0 +1,6 @@ + o Minor bugfixes: + - Clients now consider the ClientRejectInternalAddresses config option + when using a microdescriptor consensus stanza to decide whether + an exit relay would allow exiting to an internal address. Fixes + bug 7190; bugfix on 0.2.3.1-alpha. + diff --git a/changes/bug7192 b/changes/bug7192 new file mode 100644 index 0000000000..10cbc2469a --- /dev/null +++ b/changes/bug7192 @@ -0,0 +1,10 @@ + o Major bugfixes: + - When parsing exit policy summaries from microdescriptors, we had + previously been ignoring the last character in each one, so that + "accept 80,443,8080" would be treated by clients as indicating a + node that allows access to ports 80, 443, and 808. That would lead + to clients attempting connections that could never work, and + ignoring exit nodes that would support their connections. Now clients + parse these exit policy summaries correctly. Fixes bug 7192; + bugfix on 0.2.3.1-alpha. + diff --git a/src/or/policies.c b/src/or/policies.c index 6e984211ba..81e4809687 100644 --- a/src/or/policies.c +++ b/src/or/policies.c @@ -1348,8 +1348,10 @@ parse_short_policy(const char *summary) unsigned low, high; char dummy; char ent_buf[32]; + size_t len; next = comma ? comma+1 : strchr(summary, '\0'); + len = comma ? (size_t)(comma - summary) : strlen(summary); if (n_entries == MAX_EXITPOLICY_SUMMARY_LEN) { log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Impossibly long policy summary %s", @@ -1357,20 +1359,22 @@ parse_short_policy(const char *summary) return NULL; } - if (! TOR_ISDIGIT(*summary) || next-summary > (int)(sizeof(ent_buf)-1)) { + if (! TOR_ISDIGIT(*summary) || len > (sizeof(ent_buf)-1)) { /* unrecognized entry format. skip it. */ continue; } - if (next-summary < 2) { + if (len < 1) { /* empty; skip it. */ + /* XXX This happens to be unreachable, since if len==0, then *summary is + * ',' or '\0', and the TOR_ISDIGIT test above would have failed. */ continue; } - memcpy(ent_buf, summary, next-summary-1); - ent_buf[next-summary-1] = '\0'; + memcpy(ent_buf, summary, len); + ent_buf[len] = '\0'; if (tor_sscanf(ent_buf, "%u-%u%c", &low, &high, &dummy) == 2) { - if (low<1 || low>65535 || high<1 || high>65535) { + if (low<1 || low>65535 || high<1 || high>65535 || low>high) { log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Found bad entry in policy summary %s", escaped(orig_summary)); return NULL; @@ -1413,6 +1417,33 @@ parse_short_policy(const char *summary) return result; } +/** Write <b>policy</b> back out into a string. Used only for unit tests + * currently. */ +char * +write_short_policy(const short_policy_t *policy) +{ + int i; + char *answer; + smartlist_t *sl = smartlist_new(); + + smartlist_add_asprintf(sl, "%s", policy->is_accept ? "accept " : "reject "); + + for (i=0; i < policy->n_entries; i++) { + const short_policy_entry_t *e = &policy->entries[i]; + if (e->min_port == e->max_port) { + smartlist_add_asprintf(sl, "%d", e->min_port); + } else { + smartlist_add_asprintf(sl, "%d-%d", e->min_port, e->max_port); + } + if (i < policy->n_entries-1) + smartlist_add(sl, tor_strdup(",")); + } + answer = smartlist_join_strings(sl, "", 0, NULL); + SMARTLIST_FOREACH(sl, char *, a, tor_free(a)); + smartlist_free(sl); + return answer; +} + /** Release all storage held in <b>policy</b>. */ void short_policy_free(short_policy_t *policy) @@ -1431,15 +1462,14 @@ compare_tor_addr_to_short_policy(const tor_addr_t *addr, uint16_t port, int i; int found_match = 0; int accept; - (void)addr; tor_assert(port != 0); if (addr && tor_addr_is_null(addr)) addr = NULL; /* Unspec means 'no address at all,' in this context. */ - if (addr && (tor_addr_is_internal(addr, 0) || - tor_addr_is_loopback(addr))) + if (addr && get_options()->ClientRejectInternalAddresses && + (tor_addr_is_internal(addr, 0) || tor_addr_is_loopback(addr))) return ADDR_POLICY_REJECTED; for (i=0; i < policy->n_entries; ++i) { diff --git a/src/or/policies.h b/src/or/policies.h index 31f3f06c7d..f00d8299b8 100644 --- a/src/or/policies.h +++ b/src/or/policies.h @@ -61,6 +61,7 @@ void policies_free_all(void); char *policy_summarize(smartlist_t *policy); short_policy_t *parse_short_policy(const char *summary); +char *write_short_policy(const short_policy_t *policy); void short_policy_free(short_policy_t *policy); int short_policy_is_reject_star(const short_policy_t *policy); addr_policy_result_t compare_tor_addr_to_short_policy( diff --git a/src/test/test.c b/src/test/test.c index 6bf2d28d90..ddfd6337bd 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1004,6 +1004,28 @@ test_circuit_timeout(void) return; } +/* Helper: assert that short_policy parses and writes back out as itself, + or as <b>expected</b> if that's provided. */ +static void +test_short_policy_parse(const char *input, + const char *expected) +{ + short_policy_t *short_policy = NULL; + char *out = NULL; + + if (expected == NULL) + expected = input; + + short_policy = parse_short_policy(input); + tt_assert(short_policy); + out = write_short_policy(short_policy); + tt_str_op(out, ==, expected); + + done: + tor_free(out); + short_policy_free(short_policy); +} + /** Helper: Parse the exit policy string in <b>policy_str</b>, and make sure * that policies_summarize() produces the string <b>expected_summary</b> from * it. */ @@ -1014,6 +1036,7 @@ test_policy_summary_helper(const char *policy_str, config_line_t line; smartlist_t *policy = smartlist_new(); char *summary = NULL; + char *summary_after = NULL; int r; short_policy_t *short_policy = NULL; @@ -1030,8 +1053,11 @@ test_policy_summary_helper(const char *policy_str, short_policy = parse_short_policy(summary); tt_assert(short_policy); + summary_after = write_short_policy(short_policy); + test_streq(summary, summary_after); done: + tor_free(summary_after); tor_free(summary); if (policy) addr_policy_list_free(policy); @@ -1227,6 +1253,46 @@ test_policies(void) "accept *:*", "reject 1,3,5,7"); + /* Short policies with unrecognized formats should get accepted. */ + test_short_policy_parse("accept fred,2,3-5", "accept 2,3-5"); + test_short_policy_parse("accept 2,fred,3", "accept 2,3"); + test_short_policy_parse("accept 2,fred,3,bob", "accept 2,3"); + test_short_policy_parse("accept 2,-3,500-600", "accept 2,500-600"); + /* Short policies with nil entries are accepted too. */ + test_short_policy_parse("accept 1,,3", "accept 1,3"); + test_short_policy_parse("accept 100-200,,", "accept 100-200"); + test_short_policy_parse("reject ,1-10,,,,30-40", "reject 1-10,30-40"); + + /* Try parsing various broken short policies */ + tt_ptr_op(NULL, ==, parse_short_policy("accept 200-199")); + tt_ptr_op(NULL, ==, parse_short_policy("")); + tt_ptr_op(NULL, ==, parse_short_policy("rejekt 1,2,3")); + tt_ptr_op(NULL, ==, parse_short_policy("reject ")); + tt_ptr_op(NULL, ==, parse_short_policy("reject")); + tt_ptr_op(NULL, ==, parse_short_policy("rej")); + tt_ptr_op(NULL, ==, parse_short_policy("accept 2,3,100000")); + tt_ptr_op(NULL, ==, parse_short_policy("accept 2,3x,4")); + tt_ptr_op(NULL, ==, parse_short_policy("accept 2,3x,4")); + tt_ptr_op(NULL, ==, parse_short_policy("accept 2-")); + tt_ptr_op(NULL, ==, parse_short_policy("accept 2-x")); + tt_ptr_op(NULL, ==, parse_short_policy("accept 1-,3")); + tt_ptr_op(NULL, ==, parse_short_policy("accept 1-,3")); + /* Test a too-long policy. */ + { + int i; + char *policy = NULL; + smartlist_t *chunks = smartlist_new(); + smartlist_add(chunks, tor_strdup("accept ")); + for (i=1; i<10000; ++i) + smartlist_add_asprintf(chunks, "%d,", i); + smartlist_add(chunks, tor_strdup("20000")); + policy = smartlist_join_strings(chunks, "", 0, NULL); + SMARTLIST_FOREACH(chunks, char *, ch, tor_free(ch)); + smartlist_free(chunks); + tt_ptr_op(NULL, ==, parse_short_policy(policy));/* shouldn't be accepted */ + tor_free(policy); /* could leak. */ + } + /* truncation ports */ sm = smartlist_new(); for (i=1; i<2000; i+=2) { |