Add necessary code to parse and handle required/recommended protocols

This commit is contained in:
Nick Mathewson 2016-08-19 17:31:49 -04:00
parent 4df12239f6
commit cca1e0acff
4 changed files with 99 additions and 0 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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;