summaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2007-06-04 22:29:00 +0000
committerNick Mathewson <nickm@torproject.org>2007-06-04 22:29:00 +0000
commit8b0e6a446697ad3d15a1fe23a8c5c3ed53a60c70 (patch)
treed2dcdf0c97e3db1bf4852bcb0b96102c6a120bae /src/or
parent8d1224eb51bf0f9fd0c829aa7fb22e359513b71b (diff)
downloadtor-8b0e6a446697ad3d15a1fe23a8c5c3ed53a60c70.tar.gz
tor-8b0e6a446697ad3d15a1fe23a8c5c3ed53a60c70.zip
r13250@catbus: nickm | 2007-06-04 18:28:55 -0400
Adapt code to parse v3 networkstatus votes so it can also parse a consensus. Make networkstatus_vote_t the catch-all type for votes and conensuses. Correct/clarify the second argument to directory-signature. svn:r10491
Diffstat (limited to 'src/or')
-rw-r--r--src/or/dirserv.c16
-rw-r--r--src/or/dirvote.c68
-rw-r--r--src/or/or.h45
-rw-r--r--src/or/routerparse.c279
4 files changed, 270 insertions, 138 deletions
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 616c8e4d41..6852984c43 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -1897,19 +1897,19 @@ generate_networkstatus_opinion(int v2)
}
outp += strlen(outp);
} else {
- char hex_digest[HEX_DIGEST_LEN+1];
- if (tor_snprintf(outp, endp-outp, "directory-signature %s ",
- fingerprint)<0) {
+ char signing_key_fingerprint[FINGERPRINT_LEN+1];
+ if (tor_snprintf(outp, endp-outp, "directory-signature ")<0) {
log_warn(LD_BUG, "Unable to start signature line.");
goto done;
}
- if (router_get_networkstatus_v3_hash(status, digest)<0) {
- log_warn(LD_BUG, "Unable to hash network status vote");
+ outp += strlen(outp);
+
+ if (crypto_pk_get_fingerprint(private_key, signing_key_fingerprint, 0)<0) {
+ log_warn(LD_BUG, "Unable to get fingerprint for signing key");
goto done;
}
- base16_encode(hex_digest, sizeof(hex_digest), digest, DIGEST_LEN);
- outp += strlen(outp);
- if (tor_snprintf(outp, endp-outp, "%s\n", hex_digest)<0) {
+ if (tor_snprintf(outp, endp-outp, "%s %s\n", fingerprint,
+ signing_key_fingerprint)<0) {
log_warn(LD_BUG, "Unable to end signature line.");
goto done;
}
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index f45ca1fce2..ea6e8b1f04 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -26,9 +26,15 @@ networkstatus_vote_free(networkstatus_vote_t *ns)
tor_free(ns->known_flags[i]);
tor_free(ns->known_flags);
}
- tor_free(ns->nickname);
- tor_free(ns->address);
- tor_free(ns->contact);
+ if (ns->voters) {
+ SMARTLIST_FOREACH(ns->voters, networkstatus_voter_info_t *, voter,
+ {
+ tor_free(voter->nickname);
+ tor_free(voter->address);
+ tor_free(voter->contact);
+ });
+ smartlist_free(ns->voters);
+ }
if (ns->cert)
authority_cert_free(ns->cert);
@@ -47,6 +53,19 @@ networkstatus_vote_free(networkstatus_vote_t *ns)
}
/** DOCDOC */
+networkstatus_voter_info_t *
+networkstatus_get_voter_by_id(networkstatus_vote_t *vote,
+ const char *identity)
+{
+ if (!vote || !vote->voters)
+ return NULL;
+ SMARTLIST_FOREACH(vote->voters, networkstatus_voter_info_t *, voter,
+ if (!memcmp(voter->identity_digest, identity, DIGEST_LEN))
+ return voter);
+ return NULL;
+}
+
+/** DOCDOC */
static int
_compare_times(const void **_a, const void **_b)
{
@@ -92,12 +111,23 @@ median_int(smartlist_t *ints)
return *(time_t*)smartlist_get(ints, idx);
}
+static networkstatus_voter_info_t *
+get_voter(const networkstatus_vote_t *vote)
+{
+ tor_assert(vote);
+ tor_assert(vote->is_vote);
+ tor_assert(vote->voters);
+ tor_assert(smartlist_len(vote->voters) == 1);
+ return smartlist_get(vote->voters, 0);
+}
+
/** DOCDOC */
static int
_compare_votes_by_authority_id(const void **_a, const void **_b)
{
const networkstatus_vote_t *a = *_a, *b = *_b;
- return memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN);
+ return memcmp(get_voter(a)->identity_digest,
+ get_voter(b)->identity_digest, DIGEST_LEN);
}
/** DOCDOC */
@@ -193,7 +223,8 @@ compute_routerstatus_consensus(smartlist_t *votes)
++cur_n;
} else {
if (cur_n > most_n ||
- (cur && cur_n == most_n && cur->status.published_on > most_published)) {
+ (cur && cur_n == most_n &&
+ cur->status.published_on > most_published)) {
most = cur;
most_n = cur_n;
most_published = cur->status.published_on;
@@ -246,7 +277,6 @@ networkstatus_compute_consensus(smartlist_t *votes,
}
/* XXXX020 somebody needs to check vote authority. It could be this
* function, it could be somebody else. */
-
flags = smartlist_create();
/* Compute medians of time-related things, and figure out how many
@@ -363,20 +393,23 @@ networkstatus_compute_consensus(smartlist_t *votes,
char ip[INET_NTOA_BUF_LEN];
char fingerprint[HEX_DIGEST_LEN+1];
char votedigest[HEX_DIGEST_LEN+1];
+ networkstatus_voter_info_t *voter = get_voter(v);
- in.s_addr = htonl(v->addr);
+ in.s_addr = htonl(voter->addr);
tor_inet_ntoa(&in, ip, sizeof(ip));
- base16_encode(fingerprint, sizeof(fingerprint), v->identity_digest,
+ base16_encode(fingerprint, sizeof(fingerprint), voter->identity_digest,
+ DIGEST_LEN);
+ base16_encode(votedigest, sizeof(votedigest), voter->vote_digest,
DIGEST_LEN);
- base16_encode(votedigest, sizeof(votedigest), v->vote_digest, DIGEST_LEN);
tor_snprintf(buf, sizeof(buf),
"dir-source %s %s %s %s %d %d\n"
"contact %s\n"
"vote-digest %s\n",
- v->nickname, fingerprint, v->address, ip, v->dir_port,
- v->or_port,
- v->contact,
+ voter->nickname, fingerprint, voter->address, ip,
+ voter->dir_port,
+ voter->or_port,
+ voter->contact,
votedigest);
smartlist_add(chunks, tor_strdup(buf));
});
@@ -564,19 +597,21 @@ networkstatus_compute_consensus(smartlist_t *votes,
{
char digest[DIGEST_LEN];
char fingerprint[HEX_DIGEST_LEN+1];
- char hex_digest[HEX_DIGEST_LEN+1];
+ char signing_key_fingerprint[HEX_DIGEST_LEN+1];
+
char buf[4096];
smartlist_add(chunks, tor_strdup("directory-signature "));
/* Compute the hash of the chunks. */
hash_list_members(digest, chunks);
- /* Get hex stuff as needed. */
- base16_encode(hex_digest, sizeof(hex_digest), digest, DIGEST_LEN);
+ /* Get the fingerprints */
crypto_pk_get_fingerprint(identity_key, fingerprint, 0);
+ crypto_pk_get_fingerprint(signing_key, signing_key_fingerprint, 0);
/* add the junk that will go at the end of the line. */
- tor_snprintf(buf, sizeof(buf), "%s %s\n", hex_digest, fingerprint);
+ tor_snprintf(buf, sizeof(buf), "%s %s\n", fingerprint,
+ signing_key_fingerprint);
/* And the signature. */
/* XXXX020 check return */
router_append_dirobj_signature(buf, sizeof(buf), digest, signing_key);
@@ -593,3 +628,4 @@ networkstatus_compute_consensus(smartlist_t *votes,
return result;
}
+
diff --git a/src/or/or.h b/src/or/or.h
index 71c829c177..cfb6fb7d21 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1300,9 +1300,28 @@ typedef struct vote_routerstatus_t {
char *version;
} vote_routerstatus_t;
-/** DOCDOC */
+/* DOCDOC */
+typedef struct networkstatus_voter_info_t {
+ char *nickname;
+ char identity_digest[DIGEST_LEN];
+ char *address;
+ uint32_t addr;
+ uint16_t dir_port;
+ uint16_t or_port;
+ char *contact;
+ char vote_digest[DIGEST_LEN]; /* consensus only. */
+ char signing_key_digest[DIGEST_LEN]; /* This part is _not_ signed. */
+
+ char *pending_signature;
+ int pending_signature_len;
+ int bad_signature;
+} networkstatus_voter_info_t;
+
+/*XXXX020 rename to networkstatus_t once it works. */
+/** DOCDOC is vote or consensus. */
typedef struct networkstatus_vote_t {
- time_t published;
+ int is_vote;
+ time_t published; /* vote only. */
time_t valid_after;
time_t fresh_until;
time_t valid_until;
@@ -1313,20 +1332,12 @@ typedef struct networkstatus_vote_t {
char *server_versions;
char **known_flags; /* NULL-terminated */
- char *nickname;
- char identity_digest[DIGEST_LEN];
- char *address;
- uint32_t addr;
- uint16_t dir_port;
- uint16_t or_port;
-
- struct authority_cert_t *cert;
-
- char *contact;
+ smartlist_t *voters; /* list of networkstatus_voter_info_t */
- char vote_digest[DIGEST_LEN];
+ struct authority_cert_t *cert; /* vote only. */
- smartlist_t *routerstatus_list;
+ smartlist_t *routerstatus_list; /* holds vote_routerstatus_t if is_vote,
+ * otherwise just routerstatus_t. */
} networkstatus_vote_t;
/** Contents of a directory of onion routers. */
@@ -2718,6 +2729,9 @@ void networkstatus_vote_free(networkstatus_vote_t *ns);
char *networkstatus_compute_consensus(smartlist_t *votes,
crypto_pk_env_t *identity_key,
crypto_pk_env_t *signing_key);
+networkstatus_voter_info_t *networkstatus_get_voter_by_id(
+ networkstatus_vote_t *vote,
+ const char *identity);
/********************************* dns.c ***************************/
@@ -3383,7 +3397,8 @@ void assert_addr_policy_ok(addr_policy_t *t);
void dump_distinct_digest_count(int severity);
networkstatus_t *networkstatus_parse_from_string(const char *s);
-networkstatus_vote_t *networkstatus_parse_vote_from_string(const char *s);
+networkstatus_vote_t *networkstatus_parse_vote_from_string(const char *s,
+ int is_vote);
void authority_cert_free(authority_cert_t *cert);
authority_cert_t *authority_cert_parse_from_string(const char *s,
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 93f2366faf..2eee814d2e 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -311,12 +311,7 @@ static token_rule_t networkstatus_vote_token_table[] = {
END_OF_TABLE
};
-
-#if 0
-/* XXXX This stuff is commented out for now so we can avoid warnings about
- * unused variables. */
-
-static token_rule_t status_consensus_table[] = {
+static token_rule_t networkstatus_consensus_token_table[] = {
T1("network-status-version", K_NETWORK_STATUS_VERSION,
GE(1), NO_OBJ ),
T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
@@ -325,26 +320,19 @@ static token_rule_t status_consensus_table[] = {
T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
- CERTIFICATE_MEMBERS
-
T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
T1N("dir-source", K_DIR_SOURCE, GE(3), NO_OBJ ),
- T1N("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
T1N("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
T1N("vote-digest", K_VOTE_DIGEST, GE(1), NO_OBJ ),
-#if 0
- T1( "dir-options", K_DIR_OPTIONS, ARGS, NO_OBJ ),
T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
-#endif
T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
END_OF_TABLE
};
-#endif
static token_rule_t networkstatus_vote_footer_token_table[] = {
T( "directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
@@ -1786,14 +1774,14 @@ networkstatus_parse_from_string(const char *s)
/** DOCDOC */
networkstatus_vote_t *
-networkstatus_parse_vote_from_string(const char *s)
+networkstatus_parse_vote_from_string(const char *s, int is_vote)
{
smartlist_t *tokens = smartlist_create();
smartlist_t *rs_tokens = NULL, *footer_tokens = NULL;
+ networkstatus_voter_info_t *voter = NULL;
networkstatus_vote_t *ns = NULL;
- char ns_digest[DIGEST_LEN], declared_identity[DIGEST_LEN],
- declared_digest[DIGEST_LEN];
- const char *cert, *end_of_cert = NULL, *end_of_header, *end_of_footer;
+ char ns_digest[DIGEST_LEN];
+ const char *cert, *end_of_header, *end_of_footer;
directory_token_t *tok;
int ok;
struct in_addr in;
@@ -1806,31 +1794,46 @@ networkstatus_parse_vote_from_string(const char *s)
end_of_header = find_start_of_next_routerstatus(s);
if (tokenize_string(s, end_of_header, tokens,
- networkstatus_vote_token_table)) {
+ is_vote ? networkstatus_vote_token_table :
+ networkstatus_consensus_token_table)) {
log_warn(LD_DIR, "Error tokenizing network-status vote header.");
goto err;
}
ns = tor_malloc_zero(sizeof(networkstatus_vote_t));
- if (!(cert = strstr(s, "\ndir-key-certificate-version")))
- goto err;
- ++cert;
- ns->cert = authority_cert_parse_from_string(cert, &end_of_cert);
- if (!ns->cert || !end_of_cert || end_of_cert > end_of_header)
- goto err;
+
+ if (is_vote) {
+ const char *end_of_cert = NULL;
+ if (!(cert = strstr(s, "\ndir-key-certificate-version")))
+ goto err;
+ ++cert;
+ ns->cert = authority_cert_parse_from_string(cert, &end_of_cert);
+ if (!ns->cert || !end_of_cert || end_of_cert > end_of_header)
+ goto err;
+ }
tok = find_first_by_keyword(tokens, K_VOTE_STATUS);
tor_assert(tok);
tor_assert(tok->n_args);
- if (strcmp(tok->args[0], "vote")) {
- log_warn(LD_DIR, "Unrecognized vote status %s in network-status vote.",
+ if (!strcmp(tok->args[0], "vote")) {
+ ns->is_vote = 1;
+ } else if (!strcmp(tok->args[0], "consensus")) {
+ ns->is_vote = 0;
+ } else {
+ log_warn(LD_DIR, "Unrecognized vote status %s in network-status",
escaped(tok->args[0]));
goto err;
}
-
- tok = find_first_by_keyword(tokens, K_PUBLISHED);
- if (parse_iso_time(tok->args[0], &ns->published))
+ if (!bool_eq(ns->is_vote, is_vote)) {
+ log_warn(LD_DIR, "Got the wrong kind of v3 networkstatus.");
goto err;
+ }
+
+ if (ns->is_vote) {
+ tok = find_first_by_keyword(tokens, K_PUBLISHED);
+ if (parse_iso_time(tok->args[0], &ns->published))
+ goto err;
+ }
tok = find_first_by_keyword(tokens, K_VALID_AFTER);
if (parse_iso_time(tok->args[0], &ns->valid_after))
@@ -1870,55 +1873,105 @@ networkstatus_parse_vote_from_string(const char *s)
ns->known_flags[tok->n_args] = NULL;
tok->n_args = 0; /* suppress free of args members, but not of args itself. */
- tok = find_first_by_keyword(tokens, K_DIR_SOURCE);
- tor_assert(tok);
- tor_assert(tok->n_args >= 6);
- ns->nickname = tor_strdup(tok->args[0]);
- if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
- base16_decode(ns->identity_digest, sizeof(ns->identity_digest),
- tok->args[1], HEX_DIGEST_LEN) < 0) {
- log_warn(LD_DIR, "Error decoding identity digest %s in "
- "network-status vote.", escaped(tok->args[1]));
- goto err;
+ ns->voters = smartlist_create();
+
+ SMARTLIST_FOREACH(tokens, directory_token_t *, _tok,
+ {
+ tok = _tok;
+ if (tok->tp == K_DIR_SOURCE) {
+ tor_assert(tok->n_args >= 6);
+
+ if (voter)
+ smartlist_add(ns->voters, voter);
+ voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
+
+ voter->nickname = tor_strdup(tok->args[0]);
+ if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
+ base16_decode(voter->identity_digest, sizeof(voter->identity_digest),
+ tok->args[1], HEX_DIGEST_LEN) < 0) {
+ log_warn(LD_DIR, "Error decoding identity digest %s in "
+ "network-status vote.", escaped(tok->args[1]));
+ goto err;
+ }
+ voter->address = tor_strdup(tok->args[2]);
+ if (!tor_inet_aton(tok->args[3], &in)) {
+ log_warn(LD_DIR, "Error decoding IP address %s in network-status.",
+ escaped(tok->args[3]));
+ goto err;
+ }
+ voter->dir_port = (uint64_t)
+ (int) tor_parse_long(tok->args[4], 10, 0, 65535, &ok, NULL);
+ if (!ok)
+ goto err;
+ voter->or_port = (uint64_t)
+ (int) tor_parse_long(tok->args[5], 10, 0, 65535, &ok, NULL);
+ if (!ok)
+ goto err;
+ } else if (tok->tp == K_CONTACT) {
+ if (!voter || voter->contact) {
+ log_warn(LD_DIR, "contact element is out of place.");
+ goto err;
+ }
+ voter->contact = tor_strdup(tok->args[0]);
+ } else if (tok->tp == K_VOTE_DIGEST) {
+ tor_assert(!is_vote);
+ tor_assert(tok->n_args >= 1);
+ if (!voter || ! tor_digest_is_zero(voter->vote_digest)) {
+ log_warn(LD_DIR, "vote-digest element is out of place.");
+ goto err;
+ }
+ if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
+ base16_decode(voter->vote_digest, sizeof(voter->vote_digest),
+ tok->args[0], HEX_DIGEST_LEN) < 0) {
+ log_warn(LD_DIR, "Error decoding vote digest %s in "
+ "network-status consensus.", escaped(tok->args[1]));
+ goto err;
+ }
+ }
+ });
+ if (voter) {
+ smartlist_add(ns->voters, voter);
+ voter = NULL;
}
- ns->address = tor_strdup(tok->args[2]);
- if (!tor_inet_aton(tok->args[3], &in)) {
- log_warn(LD_DIR, "Error decoding IP address %s in network-status vote.",
- escaped(tok->args[3]));
+ if (smartlist_len(ns->voters) == 0) {
+ log_warn(LD_DIR, "Missing dir-source elements in a vote networkstatus.");
goto err;
- }
- ns->dir_port = (uint64_t)
- (int) tor_parse_long(tok->args[4], 10, 0, 65535, &ok, NULL);
- if (!ok)
+ } else if (is_vote && smartlist_len(ns->voters) != 1) {
+ log_warn(LD_DIR, "Too many dir-source elements in a vote networkstatus.");
goto err;
- ns->or_port = (uint64_t)
- (int) tor_parse_long(tok->args[5], 10, 0, 65535, &ok, NULL);
- if (!ok)
- goto err;
-
- tok = find_first_by_keyword(tokens, K_CONTACT);
- if (tok) {
- ns->contact = tor_strdup(tok->args[0]);
}
/* Parse routerstatus lines. */
rs_tokens = smartlist_create();
s = end_of_header;
ns->routerstatus_list = smartlist_create();
+
while (!strcmpstart(s, "r ")) {
- vote_routerstatus_t *rs = tor_malloc_zero(sizeof(vote_routerstatus_t));
- if (routerstatus_parse_entry_from_string(&s, tokens, ns, rs))
- smartlist_add(ns->routerstatus_list, rs);
- else {
- tor_free(rs->version);
- tor_free(rs);
+ if (is_vote) {
+ vote_routerstatus_t *rs = tor_malloc_zero(sizeof(vote_routerstatus_t));
+ if (routerstatus_parse_entry_from_string(&s, tokens, ns, rs))
+ smartlist_add(ns->routerstatus_list, rs);
+ else {
+ tor_free(rs->version);
+ tor_free(rs);
+ }
+ } else {
+ routerstatus_t *rs;
+ if ((rs =routerstatus_parse_entry_from_string(&s, tokens, NULL, NULL)))
+ smartlist_add(ns->routerstatus_list, rs);
}
}
for (i = 1; i < smartlist_len(ns->routerstatus_list); ++i) {
- vote_routerstatus_t *a = smartlist_get(ns->routerstatus_list, i-1);
- vote_routerstatus_t *b = smartlist_get(ns->routerstatus_list, i);
- if (memcmp(a->status.identity_digest, b->status.identity_digest,
- DIGEST_LEN) >= 0) {
+ routerstatus_t *rs1, *rs2;
+ if (is_vote) {
+ vote_routerstatus_t *a = smartlist_get(ns->routerstatus_list, i-1);
+ vote_routerstatus_t *b = smartlist_get(ns->routerstatus_list, i);
+ rs1 = &a->status; rs2 = &b->status;
+ } else {
+ rs1 = smartlist_get(ns->routerstatus_list, i-1);
+ rs2 = smartlist_get(ns->routerstatus_list, i);
+ }
+ if (memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN) >= 0) {
log_warn(LD_DIR, "Vote networkstatus entries not sorted by identity "
"digest");
goto err;
@@ -1933,40 +1986,62 @@ networkstatus_parse_vote_from_string(const char *s)
log_warn(LD_DIR, "Error tokenizing network-status vote footer.");
goto err;
}
- if (!(tok = find_first_by_keyword(footer_tokens, K_DIRECTORY_SIGNATURE))) {
- log_warn(LD_DIR, "No signature on network-status vote.");
- goto err;
- }
- tor_assert(tok->n_args >= 2);
- if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
- base16_decode(declared_identity, sizeof(ns->identity_digest),
- tok->args[0], HEX_DIGEST_LEN) < 0) {
- log_warn(LD_DIR, "Error decoding declared identity %s in "
- "network-status vote.", escaped(tok->args[1]));
- goto err;
- }
- if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
- base16_decode(declared_digest, sizeof(ns->identity_digest),
- tok->args[1], HEX_DIGEST_LEN) < 0) {
- log_warn(LD_DIR, "Error decoding declared digest %s in "
- "network-status vote.", escaped(tok->args[1]));
- goto err;
- }
- memcpy(ns->vote_digest, declared_digest, DIGEST_LEN);
- if (memcmp(declared_identity, ns->cert->cache_info.identity_digest,
- DIGEST_LEN)) {
- log_warn(LD_DIR, "Digest mismatch between declared and actual on "
- "network-status vote.");
- goto err;
- }
- if (memcmp(declared_digest, ns_digest, DIGEST_LEN)) {
- log_warn(LD_DIR, "Digest mismatch between declared and actual on "
- "network-status vote.");
- goto err;
- }
- if (check_signature_token(ns_digest, tok, ns->cert->signing_key, 0,
- "network-status vote"))
- goto err;
+
+ SMARTLIST_FOREACH(footer_tokens, directory_token_t *, _tok,
+ {
+ char declared_identity[DIGEST_LEN];
+ networkstatus_voter_info_t *v;
+ tok = _tok;
+ if (tok->tp != K_DIRECTORY_SIGNATURE)
+ continue;
+ tor_assert(tok->n_args >= 2);
+
+ if (!tok->object_type ||
+ strcmp(tok->object_type, "SIGNATURE") ||
+ tok->object_size < 128 || tok->object_size > 512) {
+ log_warn(LD_DIR, "Bad object type or length on directory-signature");
+ goto err;
+ }
+
+ if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
+ base16_decode(declared_identity, sizeof(declared_identity),
+ tok->args[0], HEX_DIGEST_LEN) < 0) {
+ log_warn(LD_DIR, "Error decoding declared identity %s in "
+ "network-status vote.", escaped(tok->args[0]));
+ goto err;
+ }
+ if (!(v = networkstatus_get_voter_by_id(ns, declared_identity))) {
+ log_warn(LD_DIR, "ID on signature on network-status vote does not match"
+ "any declared directory source.");
+ goto err;
+ }
+ if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
+ base16_decode(v->signing_key_digest, sizeof(v->signing_key_digest),
+ tok->args[1], HEX_DIGEST_LEN) < 0) {
+ log_warn(LD_DIR, "Error decoding declared digest %s in "
+ "network-status vote.", escaped(tok->args[1]));
+ goto err;
+ }
+
+ if (is_vote &&
+ memcmp(declared_identity, ns->cert->cache_info.identity_digest,
+ DIGEST_LEN)) {
+ log_warn(LD_DIR, "Digest mismatch between declared and actual on "
+ "network-status vote.");
+ goto err;
+ /* XXXX020 also check cert against dir-source line. */
+ }
+
+ if (is_vote) {
+ if (check_signature_token(ns_digest, tok, ns->cert->signing_key, 0,
+ "network-status vote"))
+ goto err;
+ } else {
+ v->pending_signature = tor_memdup(tok->object_body,
+ tok->object_size);
+ v->pending_signature_len = tok->object_size;
+ }
+ });
/* XXXX020 check dates for plausibility. ??? */
@@ -1980,6 +2055,12 @@ networkstatus_parse_vote_from_string(const char *s)
SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
smartlist_free(tokens);
}
+ if (voter) {
+ tor_free(voter->nickname);
+ tor_free(voter->address);
+ tor_free(voter->contact);
+ tor_free(voter);
+ }
if (rs_tokens) {
SMARTLIST_FOREACH(rs_tokens, directory_token_t *, t, token_free(t));
smartlist_free(rs_tokens);