aboutsummaryrefslogtreecommitdiff
path: root/src/or/dirvote.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2013-04-18 11:13:36 -0400
committerNick Mathewson <nickm@torproject.org>2013-04-18 11:13:36 -0400
commit8362f8854aa3e36b766724226a3baec4d325c1c0 (patch)
treed309eb1c3b9502b4323405f1a312f04dd868077c /src/or/dirvote.c
parentcd1cdae0fac33bca359b34dae4062fe87a351661 (diff)
parent4b15606fa2848f5112599865eb7b15ef2178e66a (diff)
downloadtor-8362f8854aa3e36b766724226a3baec4d325c1c0.tar
tor-8362f8854aa3e36b766724226a3baec4d325c1c0.tar.gz
Merge branch 'less_charbuf_rebased' into maint-0.2.4
Conflicts: src/or/dirserv.c src/or/dirserv.h src/test/test_dir.c
Diffstat (limited to 'src/or/dirvote.c')
-rw-r--r--src/or/dirvote.c200
1 files changed, 65 insertions, 135 deletions
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index 417721dc3..b02434c89 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -57,9 +57,6 @@ static char *make_consensus_method_list(int low, int high, const char *sep);
* Voting
* =====*/
-/* Overestimated. */
-#define MICRODESC_LINE_LEN 80
-
/** Return a new string containing the string representation of the vote in
* <b>v3_ns</b>, signed with our v3 signing key <b>private_signing_key</b>.
* For v3 authorities. */
@@ -67,17 +64,14 @@ char *
format_networkstatus_vote(crypto_pk_t *private_signing_key,
networkstatus_t *v3_ns)
{
- size_t len;
- char *status = NULL;
+ smartlist_t *chunks;
const char *client_versions = NULL, *server_versions = NULL;
- char *outp, *endp;
char fingerprint[FINGERPRINT_LEN+1];
char digest[DIGEST_LEN];
uint32_t addr;
- routerlist_t *rl = router_get_routerlist();
- char *version_lines = NULL;
- int r;
+ char *client_versions_line = NULL, *server_versions_line = NULL;
networkstatus_voter_info_t *voter;
+ char *status = NULL;
tor_assert(private_signing_key);
tor_assert(v3_ns->type == NS_TYPE_VOTE || v3_ns->type == NS_TYPE_OPINION);
@@ -91,43 +85,20 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
client_versions = v3_ns->client_versions;
server_versions = v3_ns->server_versions;
- if (client_versions || server_versions) {
- size_t v_len = 64;
- char *cp;
- if (client_versions)
- v_len += strlen(client_versions);
- if (server_versions)
- v_len += strlen(server_versions);
- version_lines = tor_malloc(v_len);
- cp = version_lines;
- if (client_versions) {
- r = tor_snprintf(cp, v_len-(cp-version_lines),
- "client-versions %s\n", client_versions);
- if (r < 0) {
- log_err(LD_BUG, "Insufficient memory for client-versions line");
- tor_assert(0);
- }
- cp += strlen(cp);
- }
- if (server_versions) {
- r = tor_snprintf(cp, v_len-(cp-version_lines),
- "server-versions %s\n", server_versions);
- if (r < 0) {
- log_err(LD_BUG, "Insufficient memory for server-versions line");
- tor_assert(0);
- }
- }
+ if (client_versions) {
+ tor_asprintf(&client_versions_line, "client-versions %s\n",
+ client_versions);
} else {
- version_lines = tor_strdup("");
+ client_versions_line = tor_strdup("");
+ }
+ if (server_versions) {
+ tor_asprintf(&server_versions_line, "server-versions %s\n",
+ server_versions);
+ } else {
+ server_versions_line = tor_strdup("");
}
- len = 8192;
- len += strlen(version_lines);
- len += (RS_ENTRY_LEN+MICRODESC_LINE_LEN)*smartlist_len(rl->routers);
- len += strlen("\ndirectory-footer\n");
- len += v3_ns->cert->cache_info.signed_descriptor_len;
-
- status = tor_malloc(len);
+ chunks = smartlist_new();
{
char published[ISO_TIME_LEN+1];
char va[ISO_TIME_LEN+1];
@@ -151,7 +122,7 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
params = tor_strdup("");
tor_assert(cert);
- r = tor_snprintf(status, len,
+ smartlist_add_asprintf(chunks,
"network-status-version 3\n"
"vote-status %s\n"
"consensus-methods %s\n"
@@ -160,7 +131,7 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
"fresh-until %s\n"
"valid-until %s\n"
"voting-delay %d %d\n"
- "%s" /* versions */
+ "%s%s" /* versions */
"known-flags %s\n"
"flag-thresholds %s\n"
"params %s\n"
@@ -170,7 +141,8 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
methods,
published, va, fu, vu,
v3_ns->vote_seconds, v3_ns->dist_seconds,
- version_lines,
+ client_versions_line,
+ server_versions_line,
flags,
flag_thresholds,
params,
@@ -178,93 +150,67 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
fmt_addr32(addr), voter->dir_port, voter->or_port,
voter->contact);
- if (r < 0) {
- log_err(LD_BUG, "Insufficient memory for network status line");
- tor_assert(0);
- }
-
tor_free(params);
tor_free(flags);
tor_free(flag_thresholds);
tor_free(methods);
- outp = status + strlen(status);
- endp = status + len;
if (!tor_digest_is_zero(voter->legacy_id_digest)) {
char fpbuf[HEX_DIGEST_LEN+1];
base16_encode(fpbuf, sizeof(fpbuf), voter->legacy_id_digest, DIGEST_LEN);
- r = tor_snprintf(outp, endp-outp, "legacy-dir-key %s\n", fpbuf);
- if (r < 0) {
- log_err(LD_BUG, "Insufficient memory for legacy-dir-key line");
- tor_assert(0);
- }
- outp += strlen(outp);
+ smartlist_add_asprintf(chunks, "legacy-dir-key %s\n", fpbuf);
}
- tor_assert(outp + cert->cache_info.signed_descriptor_len < endp);
- memcpy(outp, cert->cache_info.signed_descriptor_body,
- cert->cache_info.signed_descriptor_len);
-
- outp += cert->cache_info.signed_descriptor_len;
+ smartlist_add(chunks, tor_strndup(cert->cache_info.signed_descriptor_body,
+ cert->cache_info.signed_descriptor_len));
}
SMARTLIST_FOREACH_BEGIN(v3_ns->routerstatus_list, vote_routerstatus_t *,
vrs) {
+ char *rsf;
vote_microdesc_hash_t *h;
- if (routerstatus_format_entry(outp, endp-outp, &vrs->status,
- vrs->version, NS_V3_VOTE, vrs) < 0) {
- log_warn(LD_BUG, "Unable to print router status.");
- goto err;
- }
- outp += strlen(outp);
+ rsf = routerstatus_format_entry(&vrs->status,
+ vrs->version, NS_V3_VOTE, vrs);
+ if (rsf)
+ smartlist_add(chunks, rsf);
for (h = vrs->microdesc; h; h = h->next) {
- size_t mlen = strlen(h->microdesc_hash_line);
- if (outp+mlen >= endp) {
- log_warn(LD_BUG, "Can't fit microdesc line in vote.");
- }
- memcpy(outp, h->microdesc_hash_line, mlen+1);
- outp += strlen(outp);
+ smartlist_add(chunks, tor_strdup(h->microdesc_hash_line));
}
} SMARTLIST_FOREACH_END(vrs);
- r = tor_snprintf(outp, endp-outp, "directory-footer\n");
- if (r < 0) {
- log_err(LD_BUG, "Insufficient memory for directory-footer line");
- tor_assert(0);
- }
- outp += strlen(outp);
+ smartlist_add(chunks, tor_strdup("directory-footer\n"));
+
+ /* The digest includes everything up through the space after
+ * directory-signature. (Yuck.) */
+ crypto_digest_smartlist(digest, DIGEST_LEN, chunks,
+ "directory-signature ", DIGEST_SHA1);
{
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 err;
- }
- outp += strlen(outp);
-
if (crypto_pk_get_fingerprint(private_signing_key,
signing_key_fingerprint, 0)<0) {
log_warn(LD_BUG, "Unable to get fingerprint for signing key");
goto err;
}
- if (tor_snprintf(outp, endp-outp, "%s %s\n", fingerprint,
- signing_key_fingerprint)<0) {
- log_warn(LD_BUG, "Unable to end signature line.");
- goto err;
- }
- outp += strlen(outp);
+
+ smartlist_add_asprintf(chunks, "directory-signature %s %s\n", fingerprint,
+ signing_key_fingerprint);
}
- if (router_get_networkstatus_v3_hash(status, digest, DIGEST_SHA1)<0)
- goto err;
note_crypto_pk_op(SIGN_DIR);
- if (router_append_dirobj_signature(outp,endp-outp,digest, DIGEST_LEN,
- private_signing_key)<0) {
- log_warn(LD_BUG, "Unable to sign networkstatus vote.");
- goto err;
+ {
+ char *sig = router_get_dirobj_signature(digest, DIGEST_LEN,
+ private_signing_key);
+ if (!sig) {
+ log_warn(LD_BUG, "Unable to sign networkstatus vote.");
+ goto err;
+ }
+ smartlist_add(chunks, sig);
}
+ status = smartlist_join_strings(chunks, "", 0, NULL);
+
{
networkstatus_t *v;
if (!(v = networkstatus_parse_vote_from_string(status, NULL,
@@ -282,7 +228,12 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
err:
tor_free(status);
done:
- tor_free(version_lines);
+ tor_free(client_versions_line);
+ tor_free(server_versions_line);
+ if (chunks) {
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_free(chunks);
+ }
return status;
}
@@ -526,24 +477,6 @@ compute_routerstatus_consensus(smartlist_t *votes, int consensus_method,
return most;
}
-/** Given a list of strings in <b>lst</b>, set the <b>len_out</b>-byte digest
- * at <b>digest_out</b> to the hash of the concatenation of those strings,
- * computed with the algorithm <b>alg</b>. */
-static void
-hash_list_members(char *digest_out, size_t len_out,
- smartlist_t *lst, digest_algorithm_t alg)
-{
- crypto_digest_t *d;
- if (alg == DIGEST_SHA1)
- d = crypto_digest_new();
- else
- d = crypto_digest256_new(alg);
- SMARTLIST_FOREACH(lst, const char *, cp,
- crypto_digest_add_bytes(d, cp, strlen(cp)));
- crypto_digest_get_digest(d, digest_out, len_out);
- crypto_digest_free(d);
-}
-
/** Sorting helper: compare two strings based on their values as base-ten
* positive integers. (Non-integers are treated as prior to all integers, and
* compared lexically.) */
@@ -2027,12 +1960,12 @@ networkstatus_compute_consensus(smartlist_t *votes,
}
{
- char buf[4096];
+ char *buf;
/* Okay!! Now we can write the descriptor... */
/* First line goes into "buf". */
- routerstatus_format_entry(buf, sizeof(buf), &rs_out, NULL,
- rs_format, NULL);
- smartlist_add(chunks, tor_strdup(buf));
+ buf = routerstatus_format_entry(&rs_out, NULL, rs_format, NULL);
+ if (buf)
+ smartlist_add(chunks, buf);
}
/* Now an m line, if applicable. */
if (flavor == FLAV_MICRODESC &&
@@ -2144,12 +2077,12 @@ networkstatus_compute_consensus(smartlist_t *votes,
size_t digest_len =
flavor == FLAV_NS ? DIGEST_LEN : DIGEST256_LEN;
const char *algname = crypto_digest_algorithm_get_name(digest_alg);
- char sigbuf[4096];
+ char *signature;
smartlist_add(chunks, tor_strdup("directory-signature "));
/* Compute the hash of the chunks. */
- hash_list_members(digest, digest_len, chunks, digest_alg);
+ crypto_digest_smartlist(digest, digest_len, chunks, "", digest_alg);
/* Get the fingerprints */
crypto_pk_get_fingerprint(identity_key, fingerprint, 0);
@@ -2165,14 +2098,12 @@ networkstatus_compute_consensus(smartlist_t *votes,
signing_key_fingerprint);
}
/* And the signature. */
- sigbuf[0] = '\0';
- if (router_append_dirobj_signature(sigbuf, sizeof(sigbuf),
- digest, digest_len,
- signing_key)) {
+ if (!(signature = router_get_dirobj_signature(digest, digest_len,
+ signing_key))) {
log_warn(LD_BUG, "Couldn't sign consensus networkstatus.");
goto done;
}
- smartlist_add(chunks, tor_strdup(sigbuf));
+ smartlist_add(chunks, signature);
if (legacy_id_key_digest && legacy_signing_key && consensus_method >= 3) {
smartlist_add(chunks, tor_strdup("directory-signature "));
@@ -2188,14 +2119,13 @@ networkstatus_compute_consensus(smartlist_t *votes,
algname, fingerprint,
signing_key_fingerprint);
}
- sigbuf[0] = '\0';
- if (router_append_dirobj_signature(sigbuf, sizeof(sigbuf),
- digest, digest_len,
- legacy_signing_key)) {
+
+ if (!(signature = router_get_dirobj_signature(digest, digest_len,
+ legacy_signing_key))) {
log_warn(LD_BUG, "Couldn't sign consensus networkstatus.");
goto done;
}
- smartlist_add(chunks, tor_strdup(sigbuf));
+ smartlist_add(chunks, signature);
}
}