From be4a60945d724ca964d9d53f57cad6190a500077 Mon Sep 17 00:00:00 2001 From: Neel Chauhan Date: Sun, 25 Aug 2019 20:22:57 -0400 Subject: [PATCH 1/2] Check IPv6 exit policies on microdescriptors in node_exit_policy_rejects_all() --- changes/bug27284 | 5 +++++ src/feature/dirparse/microdesc_parse.c | 11 +++++++++++ src/feature/nodelist/microdesc_st.h | 2 ++ src/feature/nodelist/nodelist.c | 3 +-- 4 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 changes/bug27284 diff --git a/changes/bug27284 b/changes/bug27284 new file mode 100644 index 0000000000..14fc2082fe --- /dev/null +++ b/changes/bug27284 @@ -0,0 +1,5 @@ + o Minor bugfixes (ipv6): + - When parsing microdescriptors, we should check the IPv6 exit policy + alongside IPv4. Previously, we checked both exit policies for only + router info structures, while microdescriptors were IPv4-only. Fixes + bug 27284; bugfix on 0.2.3.1-alpha. Patch by Neel Chauhan. diff --git a/src/feature/dirparse/microdesc_parse.c b/src/feature/dirparse/microdesc_parse.c index 22cc1e272e..e02dfcf11a 100644 --- a/src/feature/dirparse/microdesc_parse.c +++ b/src/feature/dirparse/microdesc_parse.c @@ -92,6 +92,12 @@ find_start_of_next_microdesc(const char *s, const char *eos) #undef NEXT_LINE } +static inline int +policy_is_reject_star_or_null(struct short_policy_t *policy) +{ + return !policy || short_policy_is_reject_star(policy); +} + /** Parse as many microdescriptors as are found from the string starting at * s and ending at eos. If allow_annotations is set, read any * annotations we recognize and ignore ones we don't. @@ -250,6 +256,11 @@ microdescs_parse_from_string(const char *s, const char *eos, md->ipv6_exit_policy = parse_short_policy(tok->args[0]); } + if (policy_is_reject_star_or_null(md->exit_policy) && + policy_is_reject_star_or_null(md->ipv6_exit_policy)) { + md->policy_is_reject_star = 1; + } + smartlist_add(result, md); okay = 1; diff --git a/src/feature/nodelist/microdesc_st.h b/src/feature/nodelist/microdesc_st.h index c8265cb778..e017c46c79 100644 --- a/src/feature/nodelist/microdesc_st.h +++ b/src/feature/nodelist/microdesc_st.h @@ -33,6 +33,8 @@ struct microdesc_t { unsigned int no_save : 1; /** If true, this microdesc has an entry in the microdesc_map */ unsigned int held_in_map : 1; + /** True iff the exit policy for this router rejects everything. */ + unsigned int policy_is_reject_star : 1; /** Reference count: how many node_ts have a reference to this microdesc? */ unsigned int held_by_nodes; diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c index 21914c6c6d..6ae8d2bcb1 100644 --- a/src/feature/nodelist/nodelist.c +++ b/src/feature/nodelist/nodelist.c @@ -1424,8 +1424,7 @@ node_exit_policy_rejects_all(const node_t *node) if (node->ri) return node->ri->policy_is_reject_star; else if (node->md) - return node->md->exit_policy == NULL || - short_policy_is_reject_star(node->md->exit_policy); + return node->md->policy_is_reject_star; else return 1; } From 0127888b0623696d654125b4fa69200485e65a7f Mon Sep 17 00:00:00 2001 From: Neel Chauhan Date: Sun, 25 Aug 2019 22:32:07 -0400 Subject: [PATCH 2/2] Add tests for IPv6 exit policies on microdescriptors --- src/test/test_microdesc.c | 52 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c index 53ee799185..ad211c7ea8 100644 --- a/src/test/test_microdesc.c +++ b/src/test/test_microdesc.c @@ -648,6 +648,41 @@ static const char MD_PARSE_TEST_DATA[] = "ntor-onion-key k2yFqTU2vzMCQDEiE/j9UcEHxKrXMLpB3IL0or09sik=\n" "id rsa1024 2A8wYpHxnkKJ92orocvIQBzeHlE\n" "p6 allow 80\n" + /* Good 11: Normal, non-exit relay with ipv6 address */ + "onion-key\n" + "-----BEGIN RSA PUBLIC KEY-----\n" + "MIGJAoGBAM7uUtq5F6h63QNYIvC+4NcWaD0DjtnrOORZMkdpJhinXUOwce3cD5Dj\n" + "sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n" + "+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n" + "-----END RSA PUBLIC KEY-----\n" + "a [::1:2:3:4]:9090\n" + "a 18.0.0.1:9999\n" + "ntor-onion-key k2yFqTU2vzMCQDEiE/j9UcEHxKrXMLpB3IL0or09sik=\n" + "id rsa1024 2A8wYpHxnkKJ92orocvIQBzeHlE\n" + /* Good 12: Normal, exit relay with ipv6 address */ + "onion-key\n" + "-----BEGIN RSA PUBLIC KEY-----\n" + "MIGJAoGBAM7uUtq5F6h63QNYIvC+4NcWaD0DjtnrOORZMkdpJhinXUOwce3cD5Dj\n" + "sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n" + "+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n" + "-----END RSA PUBLIC KEY-----\n" + "a [::1:2:3:4]:9090\n" + "a 18.0.0.1:9999\n" + "ntor-onion-key k2yFqTU2vzMCQDEiE/j9UcEHxKrXMLpB3IL0or09sik=\n" + "p accept 20-23,43,53,79-81,88,110,143,194,220,389,443,464,531,543-544\n" + "id rsa1024 2A8wYpHxnkKJ92orocvIQBzeHlE\n" + /* Good 13: Normal, exit relay with only ipv6 exit policy */ + "onion-key\n" + "-----BEGIN RSA PUBLIC KEY-----\n" + "MIGJAoGBAM7uUtq5F6h63QNYIvC+4NcWaD0DjtnrOORZMkdpJhinXUOwce3cD5Dj\n" + "sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n" + "+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n" + "-----END RSA PUBLIC KEY-----\n" + "a [::1:2:3:4]:9090\n" + "a 18.0.0.1:9999\n" + "ntor-onion-key k2yFqTU2vzMCQDEiE/j9UcEHxKrXMLpB3IL0or09sik=\n" + "p6 accept 20-23,43,53,79-81,88,110,143,194,220,389,443,464,531,543-544\n" + "id rsa1024 2A8wYpHxnkKJ92orocvIQBzeHlE\n" ; #ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS ENABLE_GCC_WARNING(overlength-strings) @@ -665,7 +700,7 @@ test_md_parse(void *arg) smartlist_t *mds = microdescs_parse_from_string(MD_PARSE_TEST_DATA, NULL, 1, SAVED_NOWHERE, invalid); - tt_int_op(smartlist_len(mds), OP_EQ, 11); + tt_int_op(smartlist_len(mds), OP_EQ, 14); tt_int_op(smartlist_len(invalid), OP_EQ, 4); test_memeq_hex(smartlist_get(invalid,0), @@ -712,6 +747,21 @@ test_md_parse(void *arg) tt_assert(tor_addr_family(&md->ipv6_addr) == AF_INET6); tt_int_op(md->ipv6_orport, OP_EQ, 9090); + md = smartlist_get(mds, 11); + tt_assert(tor_addr_family(&md->ipv6_addr) == AF_INET6); + tt_int_op(md->ipv6_orport, OP_EQ, 9090); + tt_int_op(md->policy_is_reject_star, OP_EQ, 1); + + md = smartlist_get(mds, 12); + tt_assert(tor_addr_family(&md->ipv6_addr) == AF_INET6); + tt_int_op(md->ipv6_orport, OP_EQ, 9090); + tt_int_op(md->policy_is_reject_star, OP_EQ, 0); + + md = smartlist_get(mds, 13); + tt_assert(tor_addr_family(&md->ipv6_addr) == AF_INET6); + tt_int_op(md->ipv6_orport, OP_EQ, 9090); + tt_int_op(md->policy_is_reject_star, OP_EQ, 0); + done: SMARTLIST_FOREACH(mds, microdesc_t *, mdsc, microdesc_free(mdsc)); smartlist_free(mds);