Loading src/or/dirvote.c +109 −4 Original line number Diff line number Diff line Loading @@ -698,15 +698,17 @@ networkstatus_check_voter_signature(networkstatus_vote_t *consensus, signed_digest = tor_malloc(signed_digest_len); if (crypto_pk_public_checksig(cert->signing_key, signed_digest, voter->pending_signature, voter->pending_signature_len) != DIGEST_LEN || voter->signature, voter->signature_len) != DIGEST_LEN || memcmp(signed_digest, consensus->networkstatus_digest, DIGEST_LEN)) { log_warn(LD_DIR, "Got a bad signature."); /*XXXX020 say more*/ voter->bad_signature = 1; } else { voter->good_signature = 1; } tor_free(voter->pending_signature); /* XXXX020 did anything rely on this? * also, rename so it's no longer called "pending". */ // tor_free(voter->signature); return 0; } Loading @@ -730,7 +732,7 @@ networkstatus_check_consensus_signature(networkstatus_vote_t *consensus) ++n_unknown; continue; } if (voter->pending_signature) { if (voter->signature) { tor_assert(!voter->good_signature && !voter->bad_signature); if (!ds->v3_cert || networkstatus_check_voter_signature(consensus, voter, Loading @@ -752,6 +754,93 @@ networkstatus_check_consensus_signature(networkstatus_vote_t *consensus) return 0; } /** DOCDOC */ int networkstatus_add_consensus_signatures(networkstatus_vote_t *target, networkstatus_vote_t *src, char **new_signatures_out) { smartlist_t *added_signatures, *sigs; int r; tor_assert(target); tor_assert(src); tor_assert(! target->is_vote); tor_assert(! src->is_vote); tor_assert(new_signatures_out); *new_signatures_out = NULL; /* Are they the same consensus? */ if (memcmp(target->networkstatus_digest, src->networkstatus_digest, DIGEST_LEN)) return -1; if (target == src) return 0; added_signatures = smartlist_create(); /* For each voter in src... */ SMARTLIST_FOREACH(src->voters, networkstatus_voter_info_t *, src_voter, { networkstatus_voter_info_t *target_voter = networkstatus_get_voter_by_id(target, src_voter->identity_digest); authority_cert_t *cert; /* If the target a doesn't know about this voter, then forget it. */ if (!target_voter) continue; /* If the target already has a good signature from this voter, then skip * this one. */ if (target_voter->good_signature) continue; /* If this signature is no good, then skip. */ cert = authority_cert_get_by_digests(src_voter->identity_digest, src_voter->signing_key_digest); if (cert) { networkstatus_check_voter_signature(target, src_voter, cert); } /* If this signature is good, then replace and add. */ if (src_voter->good_signature || !target_voter->signature) { tor_free(target_voter->signature); target_voter->signature = tor_memdup(src_voter->signature, src_voter->signature_len); memcpy(target_voter->signing_key_digest, src_voter->signing_key_digest, DIGEST_LEN); target_voter->signature_len = src_voter->signature_len; target_voter->good_signature = 1; target_voter->bad_signature = 0; smartlist_add(added_signatures, target_voter); } }); sigs = smartlist_create(); SMARTLIST_FOREACH(added_signatures, networkstatus_voter_info_t *, v, { char buf[4096]; char sk[HEX_DIGEST_LEN+1]; char ik[HEX_DIGEST_LEN+1]; tor_assert(v->signature); base16_encode(sk, sizeof(sk), v->signing_key_digest, DIGEST_LEN); base16_encode(ik, sizeof(ik), v->identity_digest, DIGEST_LEN); tor_snprintf(buf, sizeof(buf), "directory-signature %s %s\n" "-----BEGIN SIGNATURE-----", ik, sk); smartlist_add(sigs, tor_strdup(buf)); base64_encode(buf, sizeof(buf), v->signature, v->signature_len); strlcat(buf, "-----END SIGNATURE-----", sizeof(buf)); smartlist_add(sigs, tor_strdup(buf)); }); *new_signatures_out = smartlist_join_strings(sigs, "", 0, NULL); SMARTLIST_FOREACH(sigs, char *, cp, tor_free(cp)); smartlist_free(sigs); r = smartlist_len(added_signatures); smartlist_free(added_signatures); return r; } /* ===== * Certificate functions * ===== */ Loading Loading @@ -876,6 +965,8 @@ typedef struct pending_vote_t { static smartlist_t *pending_vote_list = NULL; /** DOCDOC */ static char *pending_consensus_body = NULL; /** DOCDOC */ static networkstatus_vote_t *pending_consensus = NULL; /** DOCDOC */ void Loading Loading @@ -988,6 +1079,7 @@ dirvote_compute_consensus(void) int n_votes, n_voters; smartlist_t *votes = NULL; char *consensus_body = NULL; networkstatus_vote_t *consensus = NULL; authority_cert_t *my_cert; if (!pending_vote_list) Loading @@ -1011,13 +1103,26 @@ dirvote_compute_consensus(void) my_cert->identity_key, get_my_v3_authority_signing_key()); consensus = networkstatus_parse_vote_from_string(consensus_body, 0); if (!consensus) { log_warn(LD_DIR, "Couldn't parse consensus we generated!"); goto err; } tor_free(pending_consensus_body); pending_consensus_body = consensus_body; if (pending_consensus) networkstatus_vote_free(pending_consensus); pending_consensus = consensus; return 0; err: if (votes) smartlist_free(votes); tor_free(consensus_body); networkstatus_vote_free(consensus); return -1; } src/or/or.h +8 −2 Original line number Diff line number Diff line Loading @@ -1330,8 +1330,8 @@ typedef struct networkstatus_voter_info_t { char vote_digest[DIGEST_LEN]; char signing_key_digest[DIGEST_LEN]; /* This part is _not_ signed. */ char *pending_signature; int pending_signature_len; char *signature; int signature_len; unsigned int bad_signature : 1; unsigned int good_signature : 1; } networkstatus_voter_info_t; Loading Loading @@ -2792,6 +2792,9 @@ networkstatus_voter_info_t *networkstatus_get_voter_by_id( networkstatus_vote_t *vote, const char *identity); int networkstatus_check_consensus_signature(networkstatus_vote_t *consensus); int networkstatus_add_consensus_signatures(networkstatus_vote_t *target, networkstatus_vote_t *src, char **new_signatures_out); /* cert manipulation */ void authority_cert_free(authority_cert_t *cert); Loading Loading @@ -3272,6 +3275,7 @@ typedef struct trusted_dir_server_t { /** What kind of authority is this? (Bitfield.) */ authority_type_t type; /* XXXX020 this should be a list. */ authority_cert_t *v3_cert; /**< V3 key certificate for this authority */ int n_networkstatus_failures; /**< How many times have we asked for this Loading Loading @@ -3299,6 +3303,8 @@ trusted_dir_server_t *router_get_trusteddirserver_by_digest( const char *digest); trusted_dir_server_t *trusteddirserver_get_by_v3_auth_digest( const char *digest); authority_cert_t *authority_cert_get_by_digests(const char *id_digest, const char *sk_digest); void routerlist_add_family(smartlist_t *sl, routerinfo_t *router); void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, int must_be_running); Loading src/or/routerlist.c +17 −0 Original line number Diff line number Diff line Loading @@ -266,6 +266,23 @@ trusted_dirs_flush_certs_to_disk(void) trusted_dir_servers_certs_changed = 0; } /** DOCDOC */ authority_cert_t * authority_cert_get_by_digests(const char *id_digest, const char *sk_digest) { char d[DIGEST_LEN]; trusted_dir_server_t *ds = trusteddirserver_get_by_v3_auth_digest(id_digest); if (!ds || !ds->v3_cert) return NULL; crypto_pk_get_digest(ds->v3_cert->signing_key, d); if (memcmp(d, sk_digest, DIGEST_LEN)) return NULL; return ds->v3_cert; } /* Router descriptor storage. * * Routerdescs are stored in a big file, named "cached-routers". As new Loading src/or/routerparse.c +2 −2 Original line number Diff line number Diff line Loading @@ -2046,9 +2046,9 @@ networkstatus_parse_vote_from_string(const char *s, int is_vote) goto err; v->good_signature = 1; } else { v->pending_signature = tor_memdup(tok->object_body, v->signature = tor_memdup(tok->object_body, tok->object_size); v->pending_signature_len = tok->object_size; v->signature_len = tok->object_size; } }); /* XXXX020 enforce: vote must have at least one signature. */ Loading src/or/test.c +3 −3 Original line number Diff line number Diff line Loading @@ -2672,18 +2672,18 @@ test_v3_networkstatus(void) /* Check signatures. the first voter hasn't got one. The second one * does: validate it. */ voter = smartlist_get(con->voters, 0); test_assert(!voter->pending_signature); test_assert(!voter->signature); test_assert(!voter->good_signature); test_assert(!voter->bad_signature); voter = smartlist_get(con->voters, 1); test_assert(voter->pending_signature); test_assert(voter->signature); test_assert(!voter->good_signature); test_assert(!voter->bad_signature); test_assert(!networkstatus_check_voter_signature(con, smartlist_get(con->voters, 1), cert3)); test_assert(!voter->pending_signature); test_assert(voter->signature); test_assert(voter->good_signature); test_assert(!voter->bad_signature); Loading Loading
src/or/dirvote.c +109 −4 Original line number Diff line number Diff line Loading @@ -698,15 +698,17 @@ networkstatus_check_voter_signature(networkstatus_vote_t *consensus, signed_digest = tor_malloc(signed_digest_len); if (crypto_pk_public_checksig(cert->signing_key, signed_digest, voter->pending_signature, voter->pending_signature_len) != DIGEST_LEN || voter->signature, voter->signature_len) != DIGEST_LEN || memcmp(signed_digest, consensus->networkstatus_digest, DIGEST_LEN)) { log_warn(LD_DIR, "Got a bad signature."); /*XXXX020 say more*/ voter->bad_signature = 1; } else { voter->good_signature = 1; } tor_free(voter->pending_signature); /* XXXX020 did anything rely on this? * also, rename so it's no longer called "pending". */ // tor_free(voter->signature); return 0; } Loading @@ -730,7 +732,7 @@ networkstatus_check_consensus_signature(networkstatus_vote_t *consensus) ++n_unknown; continue; } if (voter->pending_signature) { if (voter->signature) { tor_assert(!voter->good_signature && !voter->bad_signature); if (!ds->v3_cert || networkstatus_check_voter_signature(consensus, voter, Loading @@ -752,6 +754,93 @@ networkstatus_check_consensus_signature(networkstatus_vote_t *consensus) return 0; } /** DOCDOC */ int networkstatus_add_consensus_signatures(networkstatus_vote_t *target, networkstatus_vote_t *src, char **new_signatures_out) { smartlist_t *added_signatures, *sigs; int r; tor_assert(target); tor_assert(src); tor_assert(! target->is_vote); tor_assert(! src->is_vote); tor_assert(new_signatures_out); *new_signatures_out = NULL; /* Are they the same consensus? */ if (memcmp(target->networkstatus_digest, src->networkstatus_digest, DIGEST_LEN)) return -1; if (target == src) return 0; added_signatures = smartlist_create(); /* For each voter in src... */ SMARTLIST_FOREACH(src->voters, networkstatus_voter_info_t *, src_voter, { networkstatus_voter_info_t *target_voter = networkstatus_get_voter_by_id(target, src_voter->identity_digest); authority_cert_t *cert; /* If the target a doesn't know about this voter, then forget it. */ if (!target_voter) continue; /* If the target already has a good signature from this voter, then skip * this one. */ if (target_voter->good_signature) continue; /* If this signature is no good, then skip. */ cert = authority_cert_get_by_digests(src_voter->identity_digest, src_voter->signing_key_digest); if (cert) { networkstatus_check_voter_signature(target, src_voter, cert); } /* If this signature is good, then replace and add. */ if (src_voter->good_signature || !target_voter->signature) { tor_free(target_voter->signature); target_voter->signature = tor_memdup(src_voter->signature, src_voter->signature_len); memcpy(target_voter->signing_key_digest, src_voter->signing_key_digest, DIGEST_LEN); target_voter->signature_len = src_voter->signature_len; target_voter->good_signature = 1; target_voter->bad_signature = 0; smartlist_add(added_signatures, target_voter); } }); sigs = smartlist_create(); SMARTLIST_FOREACH(added_signatures, networkstatus_voter_info_t *, v, { char buf[4096]; char sk[HEX_DIGEST_LEN+1]; char ik[HEX_DIGEST_LEN+1]; tor_assert(v->signature); base16_encode(sk, sizeof(sk), v->signing_key_digest, DIGEST_LEN); base16_encode(ik, sizeof(ik), v->identity_digest, DIGEST_LEN); tor_snprintf(buf, sizeof(buf), "directory-signature %s %s\n" "-----BEGIN SIGNATURE-----", ik, sk); smartlist_add(sigs, tor_strdup(buf)); base64_encode(buf, sizeof(buf), v->signature, v->signature_len); strlcat(buf, "-----END SIGNATURE-----", sizeof(buf)); smartlist_add(sigs, tor_strdup(buf)); }); *new_signatures_out = smartlist_join_strings(sigs, "", 0, NULL); SMARTLIST_FOREACH(sigs, char *, cp, tor_free(cp)); smartlist_free(sigs); r = smartlist_len(added_signatures); smartlist_free(added_signatures); return r; } /* ===== * Certificate functions * ===== */ Loading Loading @@ -876,6 +965,8 @@ typedef struct pending_vote_t { static smartlist_t *pending_vote_list = NULL; /** DOCDOC */ static char *pending_consensus_body = NULL; /** DOCDOC */ static networkstatus_vote_t *pending_consensus = NULL; /** DOCDOC */ void Loading Loading @@ -988,6 +1079,7 @@ dirvote_compute_consensus(void) int n_votes, n_voters; smartlist_t *votes = NULL; char *consensus_body = NULL; networkstatus_vote_t *consensus = NULL; authority_cert_t *my_cert; if (!pending_vote_list) Loading @@ -1011,13 +1103,26 @@ dirvote_compute_consensus(void) my_cert->identity_key, get_my_v3_authority_signing_key()); consensus = networkstatus_parse_vote_from_string(consensus_body, 0); if (!consensus) { log_warn(LD_DIR, "Couldn't parse consensus we generated!"); goto err; } tor_free(pending_consensus_body); pending_consensus_body = consensus_body; if (pending_consensus) networkstatus_vote_free(pending_consensus); pending_consensus = consensus; return 0; err: if (votes) smartlist_free(votes); tor_free(consensus_body); networkstatus_vote_free(consensus); return -1; }
src/or/or.h +8 −2 Original line number Diff line number Diff line Loading @@ -1330,8 +1330,8 @@ typedef struct networkstatus_voter_info_t { char vote_digest[DIGEST_LEN]; char signing_key_digest[DIGEST_LEN]; /* This part is _not_ signed. */ char *pending_signature; int pending_signature_len; char *signature; int signature_len; unsigned int bad_signature : 1; unsigned int good_signature : 1; } networkstatus_voter_info_t; Loading Loading @@ -2792,6 +2792,9 @@ networkstatus_voter_info_t *networkstatus_get_voter_by_id( networkstatus_vote_t *vote, const char *identity); int networkstatus_check_consensus_signature(networkstatus_vote_t *consensus); int networkstatus_add_consensus_signatures(networkstatus_vote_t *target, networkstatus_vote_t *src, char **new_signatures_out); /* cert manipulation */ void authority_cert_free(authority_cert_t *cert); Loading Loading @@ -3272,6 +3275,7 @@ typedef struct trusted_dir_server_t { /** What kind of authority is this? (Bitfield.) */ authority_type_t type; /* XXXX020 this should be a list. */ authority_cert_t *v3_cert; /**< V3 key certificate for this authority */ int n_networkstatus_failures; /**< How many times have we asked for this Loading Loading @@ -3299,6 +3303,8 @@ trusted_dir_server_t *router_get_trusteddirserver_by_digest( const char *digest); trusted_dir_server_t *trusteddirserver_get_by_v3_auth_digest( const char *digest); authority_cert_t *authority_cert_get_by_digests(const char *id_digest, const char *sk_digest); void routerlist_add_family(smartlist_t *sl, routerinfo_t *router); void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, int must_be_running); Loading
src/or/routerlist.c +17 −0 Original line number Diff line number Diff line Loading @@ -266,6 +266,23 @@ trusted_dirs_flush_certs_to_disk(void) trusted_dir_servers_certs_changed = 0; } /** DOCDOC */ authority_cert_t * authority_cert_get_by_digests(const char *id_digest, const char *sk_digest) { char d[DIGEST_LEN]; trusted_dir_server_t *ds = trusteddirserver_get_by_v3_auth_digest(id_digest); if (!ds || !ds->v3_cert) return NULL; crypto_pk_get_digest(ds->v3_cert->signing_key, d); if (memcmp(d, sk_digest, DIGEST_LEN)) return NULL; return ds->v3_cert; } /* Router descriptor storage. * * Routerdescs are stored in a big file, named "cached-routers". As new Loading
src/or/routerparse.c +2 −2 Original line number Diff line number Diff line Loading @@ -2046,9 +2046,9 @@ networkstatus_parse_vote_from_string(const char *s, int is_vote) goto err; v->good_signature = 1; } else { v->pending_signature = tor_memdup(tok->object_body, v->signature = tor_memdup(tok->object_body, tok->object_size); v->pending_signature_len = tok->object_size; v->signature_len = tok->object_size; } }); /* XXXX020 enforce: vote must have at least one signature. */ Loading
src/or/test.c +3 −3 Original line number Diff line number Diff line Loading @@ -2672,18 +2672,18 @@ test_v3_networkstatus(void) /* Check signatures. the first voter hasn't got one. The second one * does: validate it. */ voter = smartlist_get(con->voters, 0); test_assert(!voter->pending_signature); test_assert(!voter->signature); test_assert(!voter->good_signature); test_assert(!voter->bad_signature); voter = smartlist_get(con->voters, 1); test_assert(voter->pending_signature); test_assert(voter->signature); test_assert(!voter->good_signature); test_assert(!voter->bad_signature); test_assert(!networkstatus_check_voter_signature(con, smartlist_get(con->voters, 1), cert3)); test_assert(!voter->pending_signature); test_assert(voter->signature); test_assert(voter->good_signature); test_assert(!voter->bad_signature); Loading