📄 dirvote.c
字号:
lowest_id = rs->status.identity_digest;
}
});
if (!lowest_id) /* we're out of routers. */
break;
memset(flag_counts, 0, sizeof(int)*smartlist_len(flags));
smartlist_clear(matching_descs);
smartlist_clear(chosen_flags);
smartlist_clear(versions);
/* Okay, go through all the entries for this digest. */
SMARTLIST_FOREACH(votes, networkstatus_t *, v, {
if (index[v_sl_idx] >= size[v_sl_idx])
continue; /* out of entries. */
rs = smartlist_get(v->routerstatus_list, index[v_sl_idx]);
if (memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN))
continue; /* doesn't include this router. */
/* At this point, we know that we're looking at a routersatus with
* identity "lowest".
*/
++index[v_sl_idx];
++n_listing;
smartlist_add(matching_descs, rs);
if (rs->version && rs->version[0])
smartlist_add(versions, rs->version);
/* Tally up all the flags. */
for (i = 0; i < n_voter_flags[v_sl_idx]; ++i) {
if (rs->flags & (U64_LITERAL(1) << i))
++flag_counts[flag_map[v_sl_idx][i]];
}
if (rs->flags & (U64_LITERAL(1) << named_flag[v_sl_idx])) {
if (chosen_name && strcmp(chosen_name, rs->status.nickname)) {
log_notice(LD_DIR, "Conflict on naming for router: %s vs %s",
chosen_name, rs->status.nickname);
naming_conflict = 1;
}
chosen_name = rs->status.nickname;
}
});
/* We don't include this router at all unless more than half of
* the authorities we believe in list it. */
if (n_listing <= total_authorities/2)
continue;
/* Figure out the most popular opinion of what the most recent
* routerinfo and its contents are. */
rs = compute_routerstatus_consensus(matching_descs);
/* Copy bits of that into rs_out. */
tor_assert(!memcmp(lowest_id, rs->status.identity_digest, DIGEST_LEN));
memcpy(rs_out.identity_digest, lowest_id, DIGEST_LEN);
memcpy(rs_out.descriptor_digest, rs->status.descriptor_digest,
DIGEST_LEN);
rs_out.addr = rs->status.addr;
rs_out.published_on = rs->status.published_on;
rs_out.dir_port = rs->status.dir_port;
rs_out.or_port = rs->status.or_port;
if (chosen_name && !naming_conflict) {
strlcpy(rs_out.nickname, chosen_name, sizeof(rs_out.nickname));
} else {
strlcpy(rs_out.nickname, rs->status.nickname, sizeof(rs_out.nickname));
}
if (consensus_method == 1) {
is_named = chosen_named_idx >= 0 &&
(!naming_conflict && flag_counts[chosen_named_idx]);
} else {
const char *d = strmap_get_lc(name_to_id_map, rs_out.nickname);
if (!d) {
is_named = is_unnamed = 0;
} else if (!memcmp(d, lowest_id, DIGEST_LEN)) {
is_named = 1; is_unnamed = 0;
} else {
is_named = 0; is_unnamed = 1;
}
}
/* Set the flags. */
smartlist_add(chosen_flags, (char*)"s"); /* for the start of the line. */
SMARTLIST_FOREACH(flags, const char *, fl,
{
if (!strcmp(fl, "Named")) {
if (is_named)
smartlist_add(chosen_flags, (char*)fl);
} else if (!strcmp(fl, "Unnamed") && consensus_method >= 2) {
if (is_unnamed)
smartlist_add(chosen_flags, (char*)fl);
} else {
if (flag_counts[fl_sl_idx] > n_flag_voters[fl_sl_idx]/2)
smartlist_add(chosen_flags, (char*)fl);
}
});
/* Pick the version. */
if (smartlist_len(versions)) {
sort_version_list(versions, 0);
chosen_version = get_most_frequent_member(versions);
} else {
chosen_version = NULL;
}
/* Okay!! Now we can write the descriptor... */
/* First line goes into "buf". */
routerstatus_format_entry(buf, sizeof(buf), &rs_out, NULL, 1);
smartlist_add(chunks, tor_strdup(buf));
/* Second line is all flags. The "\n" is missing. */
smartlist_add(chunks,
smartlist_join_strings(chosen_flags, " ", 0, NULL));
/* Now the version line. */
if (chosen_version) {
smartlist_add(chunks, tor_strdup("\nv "));
smartlist_add(chunks, tor_strdup(chosen_version));
}
smartlist_add(chunks, tor_strdup("\n"));
/* And the loop is over and we move on to the next router */
}
tor_free(index);
tor_free(size);
tor_free(n_voter_flags);
tor_free(n_flag_voters);
for (i = 0; i < smartlist_len(votes); ++i)
tor_free(flag_map[i]);
tor_free(flag_map);
tor_free(flag_counts);
tor_free(named_flag);
tor_free(unnamed_flag);
strmap_free(name_to_id_map, NULL);
smartlist_free(matching_descs);
smartlist_free(chosen_flags);
smartlist_free(versions);
}
/* Add a signature. */
{
char digest[DIGEST_LEN];
char fingerprint[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 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", fingerprint,
signing_key_fingerprint);
/* And the signature. */
if (router_append_dirobj_signature(buf, sizeof(buf), digest,
signing_key)) {
log_warn(LD_BUG, "Couldn't sign consensus networkstatus.");
return NULL; /* This leaks, but it should never happen. */
}
smartlist_add(chunks, tor_strdup(buf));
}
result = smartlist_join_strings(chunks, "", 0, NULL);
tor_free(client_versions);
tor_free(server_versions);
smartlist_free(flags);
SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
smartlist_free(chunks);
{
networkstatus_t *c;
if (!(c = networkstatus_parse_vote_from_string(result, NULL, 0))) {
log_err(LD_BUG,"Generated a networkstatus consensus we couldn't "
"parse.");
tor_free(result);
return NULL;
}
networkstatus_vote_free(c);
}
return result;
}
/** Given a consensus vote <b>target</b> and a set of detached signatures in
* <b>sigs</b> that correspond to the same consensus, check whether there are
* any new signatures in <b>src_voter_list</b> that should be added to
* <b>target. (A signature should be added if we have no signature for that
* voter in <b>target</b> yet, or if we have no verifiable signature and the
* new signature is verifiable.) Return the number of signatures added or
* changed, or -1 if the document signed by <b>sigs</b> isn't the same
* document as <b>target</b>. */
int
networkstatus_add_detached_signatures(networkstatus_t *target,
ns_detached_signatures_t *sigs,
const char **msg_out)
{
int r = 0;
tor_assert(sigs);
tor_assert(target);
tor_assert(!target->is_vote);
/* Do the times seem right? */
if (target->valid_after != sigs->valid_after) {
*msg_out = "Valid-After times do not match "
"when adding detached signatures to consensus";
return -1;
}
if (target->fresh_until != sigs->fresh_until) {
*msg_out = "Fresh-until times do not match "
"when adding detached signatures to consensus";
return -1;
}
if (target->valid_until != sigs->valid_until) {
*msg_out = "Valid-until times do not match "
"when adding detached signatures to consensus";
return -1;
}
/* Are they the same consensus? */
if (memcmp(target->networkstatus_digest, sigs->networkstatus_digest,
DIGEST_LEN)) {
*msg_out = "Digest mismatch when adding detached signatures to consensus";
return -1;
}
/* For each voter in src... */
SMARTLIST_FOREACH(sigs->signatures, networkstatus_voter_info_t *, src_voter,
{
char voter_identity[HEX_DIGEST_LEN+1];
networkstatus_voter_info_t *target_voter =
networkstatus_get_voter_by_id(target, src_voter->identity_digest);
authority_cert_t *cert;
base16_encode(voter_identity, sizeof(voter_identity),
src_voter->identity_digest, DIGEST_LEN);
log_info(LD_DIR, "Looking at signature from %s", voter_identity);
/* If the target doesn't know about this voter, then forget it. */
if (!target_voter) {
log_info(LD_DIR, "We do not know about %s", voter_identity);
continue;
}
/* If the target already has a good signature from this voter, then skip
* this one. */
if (target_voter->good_signature) {
log_info(LD_DIR, "We already have a good signature from %s",
voter_identity);
continue;
}
/* Try checking the signature if we haven't already. */
if (!src_voter->good_signature && !src_voter->bad_signature) {
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, or we don't have any signature yet,
* then add it. */
if (src_voter->good_signature || !target_voter->signature) {
log_info(LD_DIR, "Adding signature from %s", voter_identity);
++r;
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;
} else {
log_info(LD_DIR, "Not adding signature from %s", voter_identity);
}
});
return r;
}
/** Return a newly allocated string holding the detached-signatures document
* corresponding to the signatures on <b>consensus</b>. */
char *
networkstatus_get_detached_signatures(networkstatus_t *consensus)
{
smartlist_t *elements;
char buf[4096];
char *result = NULL;
int n_sigs = 0;
tor_assert(consensus);
tor_assert(! consensus->is_vote);
elements = smartlist_create();
{
char va_buf[ISO_TIME_LEN+1], fu_buf[ISO_TIME_LEN+1],
vu_buf[ISO_TIME_LEN+1];
char d[HEX_DIGEST_LEN+1];
base16_encode(d, sizeof(d), consensus->networkstatus_digest, DIGEST_LEN);
format_iso_time(va_buf, consensus->valid_after);
format_iso_time(fu_buf, consensus->fresh_until);
format_iso_time(vu_buf, consensus->valid_until);
tor_snprintf(buf, sizeof(buf),
"consensus-digest %s\n"
"valid-after %s\n"
"fresh-until %s\n"
"valid-until %s\n", d, va_buf, fu_buf, vu_buf);
smartlist_add(elements, tor_strdup(buf));
}
SMARTLIST_FOREACH(consensus->voters, networkstatus_voter_info_t *, v,
{
char sk[HEX_DIGEST_LEN+1];
char id[HEX_DIGEST_LEN+1];
if (!v->signature || v->bad_signature)
continue;
++n_sigs;
base16_encode(sk, sizeof(sk), v->signing_key_digest, DIGEST_LEN);
base16_encode(id, sizeof(id), v->identity_digest, DIGEST_LEN);
tor_snprintf(buf, sizeof(buf),
"directory-signature %s %s\n-----BEGIN SIGNATURE-----\n",
id, sk);
smartlist_add(elements, tor_strdup(buf));
base64_encode(buf, sizeof(buf), v->signature, v->signature_len);
strlcat(buf, "-----END SIGNATURE-----\n", sizeof(buf));
smartlist_add(elements, tor_strdup(buf));
});
result = smartlist_join_strings(elements, "", 0, NULL);
SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
smartlist_free(elements);
if (!n_sigs)
tor_free(result);
return result;
}
/** Release all storage held in <b>s</b>. */
void
ns_detached_signatures_free(ns_detached_signatures_t *s)
{
if (s->signatures) {
SMARTLIST_FOREACH(s->signatures, networkstatus_voter_info_t *, v,
{
tor_free(v->signature);
tor_free(v);
});
smartlist_free(s->signatures);
}
tor_free(s);
}
/* =====
* Certificate functions
* ===== */
/** Allocate and return a new authority_cert_t with the same contents as
* <b>cert</b>. */
authority_cert_t *
authority_cert_dup(authority_cert_t *cert)
{
authority_cert_t *out = tor_malloc(sizeof(authority_cert_t));
tor_assert(cert);
memcpy(out, cert, sizeof(authority_cert_t));
/* Now copy pointed-to things. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -