diff --git a/changes/feature28361 b/changes/feature28361 new file mode 100644 index 0000000000..55bed9aea0 --- /dev/null +++ b/changes/feature28361 @@ -0,0 +1,5 @@ + o Minor feature (configuration): + - Allows configuration options EntryNodes, ExcludeNodes, + ExcludeExitNodes, ExitNodes, MiddleNodes, HSLayer2Nodes and + HSLayer3Nodes to be specified multiple times. Closes ticket + 28361. Patch by Daniel Pinto. diff --git a/doc/man/tor.1.txt b/doc/man/tor.1.txt index 860e1db33a..2e4c021983 100644 --- a/doc/man/tor.1.txt +++ b/doc/man/tor.1.txt @@ -1863,6 +1863,9 @@ different from other Tor clients: option overrides this option; if you have configured bridges and UseBridges is 1, the Bridges are used as your entry nodes. + + + This option can appear multiple times: the values from multiple lines are + spliced together. + + + The ExcludeNodes option overrides this option: any node listed in both EntryNodes and ExcludeNodes is treated as excluded. See <> for more information on how to specify nodes. @@ -1875,6 +1878,9 @@ different from other Tor clients: (Example: ExcludeNodes ABCD1234CDEF5678ABCD1234CDEF5678ABCD1234, \{cc}, 255.254.0.0/8) + + + This option can appear multiple times: the values from multiple lines are + spliced together. + + + By default, this option is treated as a preference that Tor is allowed to override in order to keep working. For example, if you try to connect to a hidden service, @@ -1900,13 +1906,19 @@ different from other Tor clients: list too. See <> for more information on how to specify nodes. See also the caveats on the <> option below. - + + + This option can appear multiple times: the values from multiple lines are + spliced together. + + + [[ExitNodes]] **ExitNodes** __node__,__node__,__...__:: A list of identity fingerprints, country codes, and address patterns of nodes to use as exit node---that is, a node that delivers traffic for you *outside* the Tor network. See <> for more information on how to specify nodes. + + + This option can appear multiple times: the values from multiple lines are + spliced together. + + + Note that if you list too few nodes here, or if you exclude too many exit nodes with ExcludeExitNodes, you can degrade functionality. For example, if none of the exits you list allows traffic on port 80 or 443, you won't @@ -1945,6 +1957,9 @@ different from other Tor clients: (Example: HSLayer2Nodes ABCD1234CDEF5678ABCD1234CDEF5678ABCD1234, \{cc}, 255.254.0.0/8) + + + This option can appear multiple times: the values from multiple lines are + spliced together. + + + When this is set, the resulting hidden service paths will look like: + @@ -2001,6 +2016,9 @@ different from other Tor clients: (Example: HSLayer3Nodes ABCD1234CDEF5678ABCD1234CDEF5678ABCD1234, \{cc}, 255.254.0.0/8) + + + This option can appear multiple times: the values from multiple lines are + spliced together. + + + When this is set by itself, the resulting hidden service paths will look like: + C - G - M - L3 - Rend + @@ -2048,7 +2066,10 @@ different from other Tor clients: to use for "middle" hops in your normal circuits. Normal circuits include all circuits except for direct connections to directory servers. Middle hops are all hops other than exit and entry. -+ + + + This option can appear multiple times: the values from multiple lines are + spliced together. + + + This is an **experimental** feature that is meant to be used by researchers and developers to test new features in the Tor network safely. Using it without care will strongly influence your anonymity. Other tor features may diff --git a/src/feature/nodelist/routerset.c b/src/feature/nodelist/routerset.c index 7234dc5441..0d123956d9 100644 --- a/src/feature/nodelist/routerset.c +++ b/src/feature/nodelist/routerset.c @@ -56,6 +56,7 @@ routerset_new(void) result->digests = digestmap_new(); result->policies = smartlist_new(); result->country_names = smartlist_new(); + result->fragile = 0; return result; } @@ -499,21 +500,32 @@ routerset_kv_parse(void *target, const config_line_t *line, char **errmsg, const void *params) { (void)params; - routerset_t **p = (routerset_t**)target; - routerset_free(*p); // clear the old value, if any. + routerset_t **lines = target; + + if (*lines && (*lines)->fragile) { + if (line->command == CONFIG_LINE_APPEND) { + (*lines)->fragile = 0; + } else { + routerset_free(*lines); // Represent empty sets as NULL + } + } + + int ret; routerset_t *rs = routerset_new(); if (routerset_parse(rs, line->value, line->key) < 0) { - routerset_free(rs); *errmsg = tor_strdup("Invalid router list."); - return -1; + ret = -1; } else { - if (routerset_is_empty(rs)) { - /* Represent empty sets as NULL. */ - routerset_free(rs); + if (!routerset_is_empty(rs)) { + if (!*lines) { + *lines = routerset_new(); + } + routerset_union(*lines, rs); } - *p = rs; - return 0; + ret = 0; } + routerset_free(rs); + return ret; } /** @@ -564,6 +576,15 @@ routerset_copy(void *dest, const void *src, const void *params) return 0; } +static void +routerset_mark_fragile(void *target, const void *params) +{ + (void)params; + routerset_t **ptr = (routerset_t **)target; + if (*ptr) + (*ptr)->fragile = 1; +} + /** * Function table to implement a routerset_t-based configuration type. **/ @@ -571,7 +592,8 @@ static const var_type_fns_t routerset_type_fns = { .kv_parse = routerset_kv_parse, .encode = routerset_encode, .clear = routerset_clear, - .copy = routerset_copy + .copy = routerset_copy, + .mark_fragile = routerset_mark_fragile, }; /** @@ -585,5 +607,6 @@ static const var_type_fns_t routerset_type_fns = { **/ const var_type_def_t ROUTERSET_type_defn = { .name = "RouterList", - .fns = &routerset_type_fns + .fns = &routerset_type_fns, + .flags = CFLG_NOREPLACE }; diff --git a/src/feature/nodelist/routerset.h b/src/feature/nodelist/routerset.h index 0e4fedf64e..18a0e31ba7 100644 --- a/src/feature/nodelist/routerset.h +++ b/src/feature/nodelist/routerset.h @@ -88,6 +88,10 @@ struct routerset_t { * routerset_refresh_countries() whenever the geoip country list is * reloaded. */ bitarray_t *countries; + /** If true, subsequent assignments to this routerset should replace + * it, not extend it. Set only on the first item in a routerset in an + * or_options_t. */ + unsigned int fragile:1; }; #endif /* defined(ROUTERSET_PRIVATE) */ #endif /* !defined(TOR_ROUTERSET_H) */ diff --git a/src/test/conf_examples/bug_31495_1/expected b/src/test/conf_examples/bug_31495_1/expected new file mode 100644 index 0000000000..246347b668 --- /dev/null +++ b/src/test/conf_examples/bug_31495_1/expected @@ -0,0 +1,2 @@ +Bridge 127.0.0.1:9050 +UseBridges 1 diff --git a/src/test/conf_examples/bug_31495_1/expected_log b/src/test/conf_examples/bug_31495_1/expected_log new file mode 100644 index 0000000000..a4b98345d6 --- /dev/null +++ b/src/test/conf_examples/bug_31495_1/expected_log @@ -0,0 +1 @@ +Configuration was valid \ No newline at end of file diff --git a/src/test/conf_examples/bug_31495_1/torrc b/src/test/conf_examples/bug_31495_1/torrc new file mode 100644 index 0000000000..ed6cccab3f --- /dev/null +++ b/src/test/conf_examples/bug_31495_1/torrc @@ -0,0 +1,2 @@ +UseBridges 1 +Bridge 127.0.0.1:9050 \ No newline at end of file diff --git a/src/test/conf_examples/bug_31495_2/error b/src/test/conf_examples/bug_31495_2/error new file mode 100644 index 0000000000..1417806c60 --- /dev/null +++ b/src/test/conf_examples/bug_31495_2/error @@ -0,0 +1 @@ +Failed to parse/validate config: You cannot set both UseBridges and EntryNodes. \ No newline at end of file diff --git a/src/test/conf_examples/bug_31495_2/torrc b/src/test/conf_examples/bug_31495_2/torrc new file mode 100644 index 0000000000..f629fff673 --- /dev/null +++ b/src/test/conf_examples/bug_31495_2/torrc @@ -0,0 +1,3 @@ +UseBridges 1 +Bridge 127.0.0.1:9050 +EntryNodes 127.0.0.1 \ No newline at end of file diff --git a/src/test/conf_examples/bug_31495_3/cmdline b/src/test/conf_examples/bug_31495_3/cmdline new file mode 100644 index 0000000000..478c1abe74 --- /dev/null +++ b/src/test/conf_examples/bug_31495_3/cmdline @@ -0,0 +1 @@ +/EntryNodes \ No newline at end of file diff --git a/src/test/conf_examples/bug_31495_3/expected b/src/test/conf_examples/bug_31495_3/expected new file mode 100644 index 0000000000..246347b668 --- /dev/null +++ b/src/test/conf_examples/bug_31495_3/expected @@ -0,0 +1,2 @@ +Bridge 127.0.0.1:9050 +UseBridges 1 diff --git a/src/test/conf_examples/bug_31495_3/expected_log b/src/test/conf_examples/bug_31495_3/expected_log new file mode 100644 index 0000000000..a4b98345d6 --- /dev/null +++ b/src/test/conf_examples/bug_31495_3/expected_log @@ -0,0 +1 @@ +Configuration was valid \ No newline at end of file diff --git a/src/test/conf_examples/bug_31495_3/torrc b/src/test/conf_examples/bug_31495_3/torrc new file mode 100644 index 0000000000..f629fff673 --- /dev/null +++ b/src/test/conf_examples/bug_31495_3/torrc @@ -0,0 +1,3 @@ +UseBridges 1 +Bridge 127.0.0.1:9050 +EntryNodes 127.0.0.1 \ No newline at end of file diff --git a/src/test/conf_examples/multiple_routerset_1/expected b/src/test/conf_examples/multiple_routerset_1/expected new file mode 100644 index 0000000000..9087aaff06 --- /dev/null +++ b/src/test/conf_examples/multiple_routerset_1/expected @@ -0,0 +1 @@ +EntryNodes 127.0.0.1,127.0.0.2,127.0.0.3 diff --git a/src/test/conf_examples/multiple_routerset_1/expected_log b/src/test/conf_examples/multiple_routerset_1/expected_log new file mode 100644 index 0000000000..a4b98345d6 --- /dev/null +++ b/src/test/conf_examples/multiple_routerset_1/expected_log @@ -0,0 +1 @@ +Configuration was valid \ No newline at end of file diff --git a/src/test/conf_examples/multiple_routerset_1/torrc b/src/test/conf_examples/multiple_routerset_1/torrc new file mode 100644 index 0000000000..44978e4b38 --- /dev/null +++ b/src/test/conf_examples/multiple_routerset_1/torrc @@ -0,0 +1,2 @@ +EntryNodes 127.0.0.1 +EntryNodes 127.0.0.2,127.0.0.3 \ No newline at end of file diff --git a/src/test/conf_examples/multiple_routerset_2/cmdline b/src/test/conf_examples/multiple_routerset_2/cmdline new file mode 100644 index 0000000000..d6e7970e53 --- /dev/null +++ b/src/test/conf_examples/multiple_routerset_2/cmdline @@ -0,0 +1 @@ +EntryNodes 127.0.0.4 \ No newline at end of file diff --git a/src/test/conf_examples/multiple_routerset_2/expected b/src/test/conf_examples/multiple_routerset_2/expected new file mode 100644 index 0000000000..34c893df79 --- /dev/null +++ b/src/test/conf_examples/multiple_routerset_2/expected @@ -0,0 +1 @@ +EntryNodes 127.0.0.4 diff --git a/src/test/conf_examples/multiple_routerset_2/expected_log b/src/test/conf_examples/multiple_routerset_2/expected_log new file mode 100644 index 0000000000..a4b98345d6 --- /dev/null +++ b/src/test/conf_examples/multiple_routerset_2/expected_log @@ -0,0 +1 @@ +Configuration was valid \ No newline at end of file diff --git a/src/test/conf_examples/multiple_routerset_2/torrc b/src/test/conf_examples/multiple_routerset_2/torrc new file mode 100644 index 0000000000..44978e4b38 --- /dev/null +++ b/src/test/conf_examples/multiple_routerset_2/torrc @@ -0,0 +1,2 @@ +EntryNodes 127.0.0.1 +EntryNodes 127.0.0.2,127.0.0.3 \ No newline at end of file diff --git a/src/test/conf_examples/multiple_routerset_3/cmdline b/src/test/conf_examples/multiple_routerset_3/cmdline new file mode 100644 index 0000000000..425f383bc3 --- /dev/null +++ b/src/test/conf_examples/multiple_routerset_3/cmdline @@ -0,0 +1 @@ ++EntryNodes 127.0.0.4 \ No newline at end of file diff --git a/src/test/conf_examples/multiple_routerset_3/expected b/src/test/conf_examples/multiple_routerset_3/expected new file mode 100644 index 0000000000..196b4814f8 --- /dev/null +++ b/src/test/conf_examples/multiple_routerset_3/expected @@ -0,0 +1 @@ +EntryNodes 127.0.0.1,127.0.0.2,127.0.0.3,127.0.0.4 diff --git a/src/test/conf_examples/multiple_routerset_3/expected_log b/src/test/conf_examples/multiple_routerset_3/expected_log new file mode 100644 index 0000000000..a4b98345d6 --- /dev/null +++ b/src/test/conf_examples/multiple_routerset_3/expected_log @@ -0,0 +1 @@ +Configuration was valid \ No newline at end of file diff --git a/src/test/conf_examples/multiple_routerset_3/torrc b/src/test/conf_examples/multiple_routerset_3/torrc new file mode 100644 index 0000000000..44978e4b38 --- /dev/null +++ b/src/test/conf_examples/multiple_routerset_3/torrc @@ -0,0 +1,2 @@ +EntryNodes 127.0.0.1 +EntryNodes 127.0.0.2,127.0.0.3 \ No newline at end of file diff --git a/src/test/conf_examples/multiple_routerset_4/cmdline b/src/test/conf_examples/multiple_routerset_4/cmdline new file mode 100644 index 0000000000..478c1abe74 --- /dev/null +++ b/src/test/conf_examples/multiple_routerset_4/cmdline @@ -0,0 +1 @@ +/EntryNodes \ No newline at end of file diff --git a/src/test/conf_examples/multiple_routerset_4/expected b/src/test/conf_examples/multiple_routerset_4/expected new file mode 100644 index 0000000000..bc790c86e3 --- /dev/null +++ b/src/test/conf_examples/multiple_routerset_4/expected @@ -0,0 +1 @@ +ControlSocket 1234 diff --git a/src/test/conf_examples/multiple_routerset_4/expected_log b/src/test/conf_examples/multiple_routerset_4/expected_log new file mode 100644 index 0000000000..a4b98345d6 --- /dev/null +++ b/src/test/conf_examples/multiple_routerset_4/expected_log @@ -0,0 +1 @@ +Configuration was valid \ No newline at end of file diff --git a/src/test/conf_examples/multiple_routerset_4/torrc b/src/test/conf_examples/multiple_routerset_4/torrc new file mode 100644 index 0000000000..dad8cb694e --- /dev/null +++ b/src/test/conf_examples/multiple_routerset_4/torrc @@ -0,0 +1,3 @@ +ControlSocket 1234 # dummy to prevent empty output +EntryNodes 127.0.0.1 +EntryNodes 127.0.0.2,127.0.0.3 \ No newline at end of file