|
@@ -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.");
|
|
|
voter->bad_signature = 1;
|
|
|
} else {
|
|
|
voter->good_signature = 1;
|
|
|
}
|
|
|
- tor_free(voter->pending_signature);
|
|
|
+
|
|
|
+ * also, rename so it's no longer called "pending". */
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -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,
|
|
@@ -752,6 +754,93 @@ networkstatus_check_consensus_signature(networkstatus_vote_t *consensus)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+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;
|
|
|
+
|
|
|
+
|
|
|
+ if (memcmp(target->networkstatus_digest, src->networkstatus_digest,
|
|
|
+ DIGEST_LEN))
|
|
|
+ return -1;
|
|
|
+ if (target == src)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ added_signatures = smartlist_create();
|
|
|
+
|
|
|
+
|
|
|
+ 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 (!target_voter)
|
|
|
+ continue;
|
|
|
+
|
|
|
+
|
|
|
+ * this one. */
|
|
|
+ if (target_voter->good_signature)
|
|
|
+ continue;
|
|
|
+
|
|
|
+
|
|
|
+ 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 (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
|
|
|
* ===== */
|
|
@@ -876,6 +965,8 @@ typedef struct pending_vote_t {
|
|
|
static smartlist_t *pending_vote_list = NULL;
|
|
|
|
|
|
static char *pending_consensus_body = NULL;
|
|
|
+
|
|
|
+static networkstatus_vote_t *pending_consensus = NULL;
|
|
|
|
|
|
|
|
|
void
|
|
@@ -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)
|
|
@@ -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;
|
|
|
}
|
|
|
|