commit cca1e0acffc7fc2814ed923cc86346175561c9a1 Author: Nick Mathewson nickm@torproject.org Date: Fri Aug 19 17:31:49 2016 -0400
Add necessary code to parse and handle required/recommended protocols --- src/or/networkstatus.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/or/networkstatus.h | 3 +++ src/or/or.h | 10 +++++++++ src/or/routerparse.c | 30 +++++++++++++++++++++++++++ 4 files changed, 99 insertions(+)
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 72af505..2eb3cd8 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -28,6 +28,7 @@ #include "microdesc.h" #include "networkstatus.h" #include "nodelist.h" +#include "protover.h" #include "relay.h" #include "router.h" #include "routerlist.h" @@ -275,6 +276,11 @@ networkstatus_vote_free(networkstatus_t *ns)
tor_free(ns->client_versions); tor_free(ns->server_versions); + tor_free(ns->recommended_client_protocols); + tor_free(ns->recommended_relay_protocols); + tor_free(ns->required_client_protocols); + tor_free(ns->required_relay_protocols); + if (ns->known_flags) { SMARTLIST_FOREACH(ns->known_flags, char *, c, tor_free(c)); smartlist_free(ns->known_flags); @@ -2364,6 +2370,56 @@ getinfo_helper_networkstatus(control_connection_t *conn, return 0; }
+/** Check whether the networkstatus <b>ns</b> lists any protocol + * versions as "required" or "recommended" that we do not support. If + * so, set *<b>warning_out</b> to a newly allocated string describing + * the problem. + * + * Return 1 if we should exit, 0 if we should not. */ +int +networkstatus_check_required_protocols(const networkstatus_t *ns, + int client_mode, + char **warning_out) +{ + const char *func = client_mode ? "client" : "relay"; + const char *required, *recommended; + char *missing = NULL; + + tor_assert(warning_out); + + if (client_mode) { + required = ns->required_client_protocols; + recommended = ns->recommended_client_protocols; + } else { + required = ns->required_relay_protocols; + recommended = ns->recommended_relay_protocols; + } + + if (!protover_all_supported(required, &missing)) { + tor_asprintf(warning_out, "At least one protocol listed as required in " + "the consensus is not supported by this version of Tor. " + "You should upgrade. This version of Tor will not work as a " + "%s on the Tor network. The missing protocols are: %s", + func, missing); + tor_free(missing); + return 1; + } + + if (! protover_all_supported(recommended, &missing)) { + tor_asprintf(warning_out, "At least one protocol listed as recommended in " + "the consensus is not supported by this version of Tor. " + "You should upgrade. This version of Tor will eventually " + "stop working as a %s on the Tor network. The missing " + "protocols are: %s", + func, missing); + tor_free(missing); + } + + tor_assert_nonfatal(missing == NULL); + + return 0; +} + /** Free all storage held locally in this module. */ void networkstatus_free_all(void) diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h index 71f36b6..da175ec 100644 --- a/src/or/networkstatus.h +++ b/src/or/networkstatus.h @@ -122,6 +122,9 @@ void document_signature_free(document_signature_t *sig); document_signature_t *document_signature_dup(const document_signature_t *sig); void networkstatus_free_all(void); int networkstatus_get_weight_scale_param(networkstatus_t *ns); +int networkstatus_check_required_protocols(const networkstatus_t *ns, + int client_mode, + char **warning_out);
#ifdef NETWORKSTATUS_PRIVATE STATIC void vote_routerstatus_free(vote_routerstatus_t *rs); diff --git a/src/or/or.h b/src/or/or.h index 39b124f..e9d41ee 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2525,6 +2525,16 @@ typedef struct networkstatus_t { * voter has no opinion. */ char *client_versions; char *server_versions; + + /** Lists of subprotocol versions which are _recommended_ for relays and + * clients, or which are _require_ for relays and clients. Tor shouldn't + * make any more network connections if a required protocol is missing. + */ + char *recommended_relay_protocols; + char *recommended_client_protocols; + char *required_relay_protocols; + char *required_client_protocols; + /** List of flags that this vote/consensus applies to routers. If a flag is * not listed here, the voter has no opinion on what its value should be. */ smartlist_t *known_flags; diff --git a/src/or/routerparse.c b/src/or/routerparse.c index abad6a8..46209ab 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -75,6 +75,10 @@ typedef enum { K_DIR_OPTIONS, K_CLIENT_VERSIONS, K_SERVER_VERSIONS, + K_RECOMMENDED_CLIENT_PROTOCOLS, + K_RECOMMENDED_RELAY_PROTOCOLS, + K_REQUIRED_CLIENT_PROTOCOLS, + K_REQUIRED_RELAY_PROTOCOLS, K_OR_ADDRESS, K_ID, K_P, @@ -461,6 +465,14 @@ static token_rule_t networkstatus_token_table[] = { T01("shared-rand-previous-value", K_PREVIOUS_SRV,EQ(2), NO_OBJ ), T01("shared-rand-current-value", K_CURRENT_SRV, EQ(2), NO_OBJ ), T0N("package", K_PACKAGE, CONCAT_ARGS, NO_OBJ ), + T01("recommended-client-protocols", K_RECOMMENDED_CLIENT_PROTOCOLS, + CONCAT_ARGS, NO_OBJ ), + T01("recommended-relay-protocols", K_RECOMMENDED_RELAY_PROTOCOLS, + CONCAT_ARGS, NO_OBJ ), + T01("required-client-protocols", K_REQUIRED_CLIENT_PROTOCOLS, + CONCAT_ARGS, NO_OBJ ), + T01("required-relay-protocols", K_REQUIRED_RELAY_PROTOCOLS, + CONCAT_ARGS, NO_OBJ ),
CERTIFICATE_MEMBERS
@@ -502,6 +514,15 @@ static token_rule_t networkstatus_consensus_token_table[] = { T01("shared-rand-previous-value", K_PREVIOUS_SRV, EQ(2), NO_OBJ ), T01("shared-rand-current-value", K_CURRENT_SRV, EQ(2), NO_OBJ ),
+ T01("recommended-client-protocols", K_RECOMMENDED_CLIENT_PROTOCOLS, + CONCAT_ARGS, NO_OBJ ), + T01("recommended-relay-protocols", K_RECOMMENDED_RELAY_PROTOCOLS, + CONCAT_ARGS, NO_OBJ ), + T01("required-client-protocols", K_REQUIRED_CLIENT_PROTOCOLS, + CONCAT_ARGS, NO_OBJ ), + T01("required-relay-protocols", K_REQUIRED_RELAY_PROTOCOLS, + CONCAT_ARGS, NO_OBJ ), + END_OF_TABLE };
@@ -3651,6 +3672,15 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, } }
+ if ((tok = find_opt_by_keyword(tokens, K_RECOMMENDED_CLIENT_PROTOCOLS))) + ns->recommended_client_protocols = tor_strdup(tok->args[0]); + if ((tok = find_opt_by_keyword(tokens, K_RECOMMENDED_RELAY_PROTOCOLS))) + ns->recommended_relay_protocols = tor_strdup(tok->args[0]); + if ((tok = find_opt_by_keyword(tokens, K_REQUIRED_CLIENT_PROTOCOLS))) + ns->required_client_protocols = tor_strdup(tok->args[0]); + if ((tok = find_opt_by_keyword(tokens, K_REQUIRED_RELAY_PROTOCOLS))) + ns->required_relay_protocols = tor_strdup(tok->args[0]); + tok = find_by_keyword(tokens, K_VALID_AFTER); if (parse_iso_time(tok->args[0], &ns->valid_after)) goto err;
tor-commits@lists.torproject.org