diff options
Diffstat (limited to 'src/or/routerparse.c')
-rw-r--r-- | src/or/routerparse.c | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 9e5f37b4b..e35ece06d 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -102,6 +102,7 @@ typedef enum { K_VOTING_DELAY, K_KNOWN_FLAGS, + K_PARAMS, K_VOTE_DIGEST, K_CONSENSUS_DIGEST, K_CONSENSUS_METHODS, @@ -433,6 +434,7 @@ static token_rule_t networkstatus_token_table[] = { T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ), T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ), T1("known-flags", K_KNOWN_FLAGS, ARGS, NO_OBJ ), + T01("params", K_PARAMS, ARGS, NO_OBJ ), T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ), CERTIFICATE_MEMBERS @@ -470,6 +472,7 @@ static token_rule_t networkstatus_consensus_token_table[] = { T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ), T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ), T01("consensus-method", K_CONSENSUS_METHOD, EQ(1), NO_OBJ), + T01("params", K_PARAMS, ARGS, NO_OBJ ), END_OF_TABLE }; @@ -2002,8 +2005,9 @@ routerstatus_parse_entry_from_string(memarea_t *area, for (i=0; i < tok->n_args; ++i) { if (!strcmpstart(tok->args[i], "Bandwidth=")) { int ok; - rs->bandwidth = tor_parse_ulong(strchr(tok->args[i], '=')+1, 10, - 0, UINT32_MAX, &ok, NULL); + rs->bandwidth = (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1, + 10, 0, UINT32_MAX, + &ok, NULL); if (!ok) { log_warn(LD_DIR, "Invalid Bandwidth %s", escaped(tok->args[i])); goto err; @@ -2011,8 +2015,9 @@ routerstatus_parse_entry_from_string(memarea_t *area, rs->has_bandwidth = 1; } else if (!strcmpstart(tok->args[i], "Measured=")) { int ok; - rs->measured_bw = tor_parse_ulong(strchr(tok->args[i], '=')+1, 10, - 0, UINT32_MAX, &ok, NULL); + rs->measured_bw = + (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1, + 10, 0, UINT32_MAX, &ok, NULL); if (!ok) { log_warn(LD_DIR, "Invalid Measured Bandwidth %s", escaped(tok->args[i])); @@ -2406,6 +2411,34 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, goto err; } + tok = find_opt_by_keyword(tokens, K_PARAMS); + if (tok) { + inorder = 1; + ns->net_params = smartlist_create(); + for (i = 0; i < tok->n_args; ++i) { + int ok=0; + char *eq = strchr(tok->args[i], '='); + if (!eq) { + log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i])); + goto err; + } + tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL); + if (!ok) { + log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i])); + goto err; + } + if (i > 0 && strcmp(tok->args[i-1], tok->args[i]) >= 0) { + log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]); + inorder = 0; + } + smartlist_add(ns->net_params, tor_strdup(tok->args[i])); + } + if (!inorder) { + log_warn(LD_DIR, "params not in order"); + goto err; + } + } + ns->voters = smartlist_create(); SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) { @@ -2605,6 +2638,14 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, } else { if (tok->object_size >= INT_MAX) goto err; + /* We already parsed a vote from this voter. Use the first one. */ + if (v->signature) { + log_fn(LOG_PROTOCOL_WARN, LD_DIR, "We received a networkstatus " + "that contains two votes from the same voter. Ignoring " + "the second vote."); + continue; + } + v->signature = tor_memdup(tok->object_body, tok->object_size); v->signature_len = (int) tok->object_size; } @@ -2614,6 +2655,10 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, if (! n_signatures) { log_warn(LD_DIR, "No signatures on networkstatus vote."); goto err; + } else if (ns->type == NS_TYPE_VOTE && n_signatures != 1) { + log_warn(LD_DIR, "Received more than one signature on a " + "network-status vote."); + goto err; } if (eos_out) @@ -3516,9 +3561,11 @@ tor_version_parse(const char *s, tor_version_t *out) if (! close_paren) return -1; cp += 5; - hexlen = (close_paren-cp); + if (close_paren-cp > HEX_DIGEST_LEN) + return -1; + hexlen = (int)(close_paren-cp); memset(digest, 0, sizeof(digest)); - if (hexlen > HEX_DIGEST_LEN || hexlen == 0 || (hexlen % 2) == 1) + if ( hexlen == 0 || (hexlen % 2) == 1) return -1; if (base16_decode(digest, hexlen/2, cp, hexlen)) return -1; |