mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Prop140, continued: accept "diff/<HASH>" in URLs, per proposal.
This commit is contained in:
parent
afef059795
commit
eb3c8d376d
@ -3661,6 +3661,27 @@ warn_consensus_is_too_old(const struct consensus_cache_entry_t *consensus,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a single hex-encoded sha3-256 digest from <b>hex</b> into
|
||||
* <b>digest</b>. Return 0 on success. On failure, report that the hash came
|
||||
* from <b>location</b>, report that we are taking <b>action</b> with it, and
|
||||
* return -1.
|
||||
*/
|
||||
static int
|
||||
parse_one_diff_hash(uint8_t *digest, const char *hex, const char *location,
|
||||
const char *action)
|
||||
{
|
||||
if (base16_decode((char*)digest, DIGEST256_LEN, hex, strlen(hex)) ==
|
||||
DIGEST256_LEN) {
|
||||
return 0;
|
||||
} else {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_DIR,
|
||||
"%s contained bogus digest %s; %s.",
|
||||
location, escaped(hex), action);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/** If there is an X-Or-Diff-From-Consensus header included in <b>headers</b>,
|
||||
* set <b>digest_out<b> to a new smartlist containing every 256-bit
|
||||
* hex-encoded digest listed in that header and return 0. Otherwise return
|
||||
@ -3678,13 +3699,9 @@ parse_or_diff_from_header(smartlist_t **digests_out, const char *headers)
|
||||
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
|
||||
SMARTLIST_FOREACH_BEGIN(hex_digests, const char *, hex) {
|
||||
uint8_t digest[DIGEST256_LEN];
|
||||
if (base16_decode((char*)digest, sizeof(digest), hex, strlen(hex)) ==
|
||||
DIGEST256_LEN) {
|
||||
if (!parse_one_diff_hash(digest, hex, "X-Or-Diff-From-Consensus header",
|
||||
"ignoring")) {
|
||||
smartlist_add(*digests_out, tor_memdup(digest, sizeof(digest)));
|
||||
} else {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_DIR,
|
||||
"X-Or-Diff-From-Consensus header contained bogus digest %s; "
|
||||
"ignoring.", escaped(hex));
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(hex);
|
||||
SMARTLIST_FOREACH(hex_digests, char *, cp, tor_free(cp));
|
||||
@ -3821,18 +3838,20 @@ handle_get_current_consensus(dir_connection_t *conn,
|
||||
long lifetime = NETWORKSTATUS_CACHE_LIFETIME;
|
||||
|
||||
time_t now = time(NULL);
|
||||
const char *want_fps = NULL;
|
||||
const char *want_fps = NULL, *after_flavor = NULL;
|
||||
char *flavor = NULL;
|
||||
int flav = FLAV_NS;
|
||||
#define CONSENSUS_URL_PREFIX "/tor/status-vote/current/consensus/"
|
||||
#define CONSENSUS_FLAVORED_PREFIX "/tor/status-vote/current/consensus-"
|
||||
const char CONSENSUS_URL_PREFIX[] = "/tor/status-vote/current/consensus/";
|
||||
const char CONSENSUS_FLAVORED_PREFIX[] =
|
||||
"/tor/status-vote/current/consensus-";
|
||||
|
||||
/* figure out the flavor if any, and who we wanted to sign the thing */
|
||||
if (!strcmpstart(url, CONSENSUS_FLAVORED_PREFIX)) {
|
||||
const char *f, *cp;
|
||||
f = url + strlen(CONSENSUS_FLAVORED_PREFIX);
|
||||
cp = strchr(f, '/');
|
||||
if (cp) {
|
||||
want_fps = cp+1;
|
||||
after_flavor = cp+1;
|
||||
flavor = tor_strndup(f, cp-f);
|
||||
} else {
|
||||
flavor = tor_strdup(f);
|
||||
@ -3842,19 +3861,53 @@ handle_get_current_consensus(dir_connection_t *conn,
|
||||
flav = FLAV_NS;
|
||||
} else {
|
||||
if (!strcmpstart(url, CONSENSUS_URL_PREFIX))
|
||||
want_fps = url+strlen(CONSENSUS_URL_PREFIX);
|
||||
after_flavor = url+strlen(CONSENSUS_URL_PREFIX);
|
||||
}
|
||||
|
||||
/* see whether we've been asked explicitly for a diff from an older
|
||||
* consensus. (The user might also have said that a diff would be okay,
|
||||
* via X-Or-Diff-From-Consensus */
|
||||
const char DIFF_COMPONENT[] = "diff/";
|
||||
char *diff_hash_in_url = NULL;
|
||||
if (after_flavor && !strcmpstart(after_flavor, DIFF_COMPONENT)) {
|
||||
after_flavor += strlen(DIFF_COMPONENT);
|
||||
const char *cp = strchr(after_flavor, '/');
|
||||
if (cp) {
|
||||
diff_hash_in_url = tor_strndup(after_flavor, cp-after_flavor);
|
||||
want_fps = cp+1;
|
||||
} else {
|
||||
diff_hash_in_url = tor_strdup(after_flavor);
|
||||
want_fps = NULL;
|
||||
}
|
||||
} else {
|
||||
want_fps = after_flavor;
|
||||
}
|
||||
|
||||
struct consensus_cache_entry_t *cached_consensus = NULL;
|
||||
smartlist_t *diff_from_digests = NULL;
|
||||
compress_method_t compression_used = NO_METHOD;
|
||||
if (!parse_or_diff_from_header(&diff_from_digests, args->headers)) {
|
||||
if (diff_hash_in_url) {
|
||||
uint8_t diff_from[DIGEST256_LEN];
|
||||
diff_from_digests = smartlist_new();
|
||||
if (!parse_one_diff_hash(diff_from, diff_hash_in_url, "URL",
|
||||
"rejecting")) {
|
||||
smartlist_add(diff_from_digests, tor_memdup(diff_from, DIGEST256_LEN));
|
||||
}
|
||||
} else if (!parse_or_diff_from_header(&diff_from_digests, args->headers)) {
|
||||
tor_assert(diff_from_digests);
|
||||
}
|
||||
|
||||
if (diff_from_digests) {
|
||||
cached_consensus = find_best_diff(diff_from_digests, flav,
|
||||
args->compression_supported,
|
||||
&compression_used);
|
||||
SMARTLIST_FOREACH(diff_from_digests, uint8_t *, d, tor_free(d));
|
||||
smartlist_free(diff_from_digests);
|
||||
}
|
||||
|
||||
if (diff_hash_in_url && !cached_consensus) {
|
||||
write_http_status_line(conn, 404, "No such diff available");
|
||||
// XXXX warn_consensus_is_too_old(v, flavor, now);
|
||||
geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (! cached_consensus) {
|
||||
@ -3877,7 +3930,6 @@ handle_get_current_consensus(dir_connection_t *conn,
|
||||
write_http_status_line(conn, 404, "Consensus is too old");
|
||||
warn_consensus_is_too_old(cached_consensus, flavor, now);
|
||||
geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
|
||||
tor_free(flavor);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -3886,7 +3938,6 @@ handle_get_current_consensus(dir_connection_t *conn,
|
||||
write_http_status_line(conn, 404, "Consensus not signed by sufficient "
|
||||
"number of requested authorities");
|
||||
geoip_note_ns_response(GEOIP_REJECT_NOT_ENOUGH_SIGS);
|
||||
tor_free(flavor);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -3898,7 +3949,6 @@ handle_get_current_consensus(dir_connection_t *conn,
|
||||
spooled = spooled_resource_new_from_cache_entry(cached_consensus);
|
||||
smartlist_add(conn->spool, spooled);
|
||||
}
|
||||
tor_free(flavor);
|
||||
}
|
||||
|
||||
lifetime = (have_fresh_until && fresh_until > now) ? fresh_until - now : 0;
|
||||
@ -3964,6 +4014,8 @@ handle_get_current_consensus(dir_connection_t *conn,
|
||||
goto done;
|
||||
|
||||
done:
|
||||
tor_free(flavor);
|
||||
tor_free(diff_hash_in_url);
|
||||
if (clear_spool) {
|
||||
dir_conn_clear_spool(conn);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user