diff options
author | Nick Mathewson <nickm@torproject.org> | 2013-04-18 11:16:05 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2013-04-18 11:16:05 -0400 |
commit | da30adcf0fd048d1f2e7a4b76e2c880cc3824e6e (patch) | |
tree | eef8ad038eb361e3241c3b8f9997478c8522ce55 /src/or/dirserv.c | |
parent | 5f035e2c6501fe166900cb493e2c3de51371c9c5 (diff) | |
parent | 9fec0c1a95ab24f5f18d6995e30fe2111e6b7db2 (diff) | |
download | tor-da30adcf0fd048d1f2e7a4b76e2c880cc3824e6e.tar.gz tor-da30adcf0fd048d1f2e7a4b76e2c880cc3824e6e.zip |
Merge remote-tracking branch 'origin/maint-0.2.4'
Conflicts:
src/common/crypto.c
Diffstat (limited to 'src/or/dirserv.c')
-rw-r--r-- | src/or/dirserv.c | 153 |
1 files changed, 60 insertions, 93 deletions
diff --git a/src/or/dirserv.c b/src/or/dirserv.c index acb8c5cd91..e15cf7d39c 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -2311,11 +2311,10 @@ version_from_platform(const char *platform) return NULL; } -/** Helper: write the router-status information in <b>rs</b> into <b>buf</b>, - * which has at least <b>buf_len</b> free characters. Do NUL-termination. - * Use the same format as in network-status documents. If <b>version</b> is - * non-NULL, add a "v" line for the platform. Return 0 on success, -1 on - * failure. +/** Helper: write the router-status information in <b>rs</b> into a newly + * allocated character buffer. Use the same format as in network-status + * documents. If <b>version</b> is non-NULL, add a "v" line for the platform. + * Return 0 on success, -1 on failure. * * The format argument has one of the following values: * NS_V2 - Output an entry suitable for a V2 NS opinion document @@ -2326,25 +2325,25 @@ version_from_platform(const char *platform) * it contains additional information for the vote. * NS_CONTROL_PORT - Output a NS document for the control port */ -int -routerstatus_format_entry(char *buf, size_t buf_len, - const routerstatus_t *rs, const char *version, +char * +routerstatus_format_entry(const routerstatus_t *rs, const char *version, routerstatus_format_type_t format, const vote_routerstatus_t *vrs) { - int r; - char *cp; char *summary; + char *result = NULL; char published[ISO_TIME_LEN+1]; char identity64[BASE64_DIGEST_LEN+1]; char digest64[BASE64_DIGEST_LEN+1]; + smartlist_t *chunks = NULL; format_iso_time(published, rs->published_on); digest_to_base64(identity64, rs->identity_digest); digest_to_base64(digest64, rs->descriptor_digest); - r = tor_snprintf(buf, buf_len, + chunks = smartlist_new(); + smartlist_add_asprintf(chunks, "r %s %s %s%s%s %s %d %d\n", rs->nickname, identity64, @@ -2354,11 +2353,6 @@ routerstatus_format_entry(char *buf, size_t buf_len, fmt_addr32(rs->addr), (int)rs->or_port, (int)rs->dir_port); - if (r<0) { - log_warn(LD_BUG, "Not enough space in buffer."); - return -1; - } - cp = buf + strlen(buf); /* TODO: Maybe we want to pass in what we need to build the rest of * this here, instead of in the caller. Then we could use the @@ -2367,25 +2361,18 @@ routerstatus_format_entry(char *buf, size_t buf_len, /* V3 microdesc consensuses don't have "a" lines. */ if (format == NS_V3_CONSENSUS_MICRODESC) - return 0; + goto done; /* Possible "a" line. At most one for now. */ if (!tor_addr_is_null(&rs->ipv6_addr)) { - r = tor_snprintf(cp, buf_len - (cp-buf), - "a %s\n", - fmt_addrport(&rs->ipv6_addr, rs->ipv6_orport)); - if (r<0) { - log_warn(LD_BUG, "Not enough space in buffer."); - return -1; - } - cp += strlen(cp); + smartlist_add_asprintf(chunks, "a %s\n", + fmt_addrport(&rs->ipv6_addr, rs->ipv6_orport)); } if (format == NS_V3_CONSENSUS) - return 0; + goto done; - /* NOTE: Whenever this list expands, be sure to increase MAX_FLAG_LINE_LEN*/ - r = tor_snprintf(cp, buf_len - (cp-buf), + smartlist_add_asprintf(chunks, "s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", /* These must stay in alphabetical order. */ rs->is_authority?" Authority":"", @@ -2401,20 +2388,11 @@ routerstatus_format_entry(char *buf, size_t buf_len, rs->is_unnamed?" Unnamed":"", rs->is_v2_dir?" V2Dir":"", rs->is_valid?" Valid":""); - if (r<0) { - log_warn(LD_BUG, "Not enough space in buffer."); - return -1; - } - cp += strlen(cp); /* length of "opt v \n" */ #define V_LINE_OVERHEAD 7 if (version && strlen(version) < MAX_V_LINE_LEN - V_LINE_OVERHEAD) { - if (tor_snprintf(cp, buf_len - (cp-buf), "v %s\n", version)<0) { - log_warn(LD_BUG, "Unable to print router version."); - return -1; - } - cp += strlen(cp); + smartlist_add_asprintf(chunks, "v %s\n", version); } if (format != NS_V2) { @@ -2434,7 +2412,7 @@ routerstatus_format_entry(char *buf, size_t buf_len, log_warn(LD_BUG, "Cannot get any descriptor for %s " "(wanted descriptor %s).", id, dd); - return -1; + goto err; } /* This assert could fire for the control port, because @@ -2469,39 +2447,32 @@ routerstatus_format_entry(char *buf, size_t buf_len, tor_assert(desc); bw_kb = router_get_advertised_bandwidth_capped(desc) / 1000; } - r = tor_snprintf(cp, buf_len - (cp-buf), - "w Bandwidth=%d\n", bw_kb); + smartlist_add_asprintf(chunks, + "w Bandwidth=%d", bw_kb); - if (r<0) { - log_warn(LD_BUG, "Not enough space in buffer."); - return -1; - } - cp += strlen(cp); if (format == NS_V3_VOTE && vrs && vrs->has_measured_bw) { - *--cp = '\0'; /* Kill "\n" */ - r = tor_snprintf(cp, buf_len - (cp-buf), - " Measured=%d\n", vrs->measured_bw_kb); - if (r<0) { - log_warn(LD_BUG, "Not enough space in buffer for weight line."); - return -1; - } - cp += strlen(cp); + smartlist_add_asprintf(chunks, + " Measured=%d", vrs->measured_bw_kb); } + smartlist_add(chunks, tor_strdup("\n")); if (desc) { summary = policy_summarize(desc->exit_policy, AF_INET); - r = tor_snprintf(cp, buf_len - (cp-buf), "p %s\n", summary); - if (r<0) { - log_warn(LD_BUG, "Not enough space in buffer."); - tor_free(summary); - return -1; - } - cp += strlen(cp); + smartlist_add_asprintf(chunks, "p %s\n", summary); tor_free(summary); } } - return 0; + done: + result = smartlist_join_strings(chunks, "", 0, NULL); + + err: + if (chunks) { + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_free(chunks); + } + + return result; } /** Helper for sorting: compares two routerinfos first by address, and then by @@ -3191,14 +3162,13 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, /** For v2 authoritative directories only: Replace the contents of * <b>the_v2_networkstatus</b> with a newly generated network status * object. */ -static cached_dir_t * +cached_dir_t * generate_v2_networkstatus_opinion(void) { cached_dir_t *r = NULL; - size_t len, identity_pkey_len; + size_t identity_pkey_len; char *status = NULL, *client_versions = NULL, *server_versions = NULL, *identity_pkey = NULL, *hostname = NULL; - char *outp, *endp; const or_options_t *options = get_options(); char fingerprint[FINGERPRINT_LEN+1]; char published[ISO_TIME_LEN+1]; @@ -3217,6 +3187,7 @@ generate_v2_networkstatus_opinion(void) char *version_lines = NULL; smartlist_t *routers = NULL; digestmap_t *omit_as_sybil = NULL; + smartlist_t *chunks = NULL; private_key = get_server_identity_key(); @@ -3255,12 +3226,8 @@ generate_v2_networkstatus_opinion(void) version_lines = tor_strdup(""); } - len = 4096+strlen(client_versions)+strlen(server_versions); - len += identity_pkey_len*2; - len += (RS_ENTRY_LEN)*smartlist_len(rl->routers); - - status = tor_malloc(len); - tor_snprintf(status, len, + chunks = smartlist_new(); + smartlist_add_asprintf(chunks, "network-status-version 2\n" "dir-source %s %s %d\n" "fingerprint %s\n" @@ -3280,8 +3247,6 @@ generate_v2_networkstatus_opinion(void) versioning ? " Versions" : "", version_lines, identity_pkey); - outp = status + strlen(status); - endp = status + len; /* precompute this part, since we need it to decide what "stable" * means. */ @@ -3312,35 +3277,33 @@ generate_v2_networkstatus_opinion(void) if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest)) clear_status_flags_on_sybil(&rs); - if (routerstatus_format_entry(outp, endp-outp, &rs, version, NS_V2, - NULL)) { - log_warn(LD_BUG, "Unable to print router status."); - tor_free(version); - goto done; + { + char *rsf = routerstatus_format_entry(&rs, version, NS_V2, NULL); + if (rsf) + smartlist_add(chunks, rsf); } tor_free(version); - outp += strlen(outp); } } SMARTLIST_FOREACH_END(ri); - if (tor_snprintf(outp, endp-outp, "directory-signature %s\n", - options->Nickname)<0) { - log_warn(LD_BUG, "Unable to write signature line."); - goto done; - } - if (router_get_networkstatus_v2_hash(status, digest)<0) { - log_warn(LD_BUG, "Unable to hash network status"); - goto done; - } - outp += strlen(outp); + smartlist_add_asprintf(chunks, "directory-signature %s\n", + options->Nickname); + + crypto_digest_smartlist(digest, DIGEST_LEN, chunks, "", DIGEST_SHA1); note_crypto_pk_op(SIGN_DIR); - if (router_append_dirobj_signature(outp,endp-outp,digest,DIGEST_LEN, - private_key)<0) { - log_warn(LD_BUG, "Unable to sign router status."); - goto done; + { + char *sig; + if (!(sig = router_get_dirobj_signature(digest,DIGEST_LEN, + private_key))) { + log_warn(LD_BUG, "Unable to sign router status."); + goto done; + } + smartlist_add(chunks, sig); } + status = smartlist_join_strings(chunks, "", 0, NULL); + { networkstatus_v2_t *ns; if (!(ns = networkstatus_v2_parse_from_string(status))) { @@ -3362,6 +3325,10 @@ generate_v2_networkstatus_opinion(void) } done: + if (chunks) { + SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); + smartlist_free(chunks); + } tor_free(client_versions); tor_free(server_versions); tor_free(version_lines); |