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;
}
++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,
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
* ===== */
static smartlist_t *pending_vote_list = NULL;
/** DOCDOC */
static char *pending_consensus_body = NULL;
+/** DOCDOC */
+static networkstatus_vote_t *pending_consensus = NULL;
/** DOCDOC */
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)
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;
}
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;
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);
/** 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
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);