mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Fix a consensus-extension bug found by outofwords
When the bandwidth-weights branch added the "directory-footer" token, and began parsing the directory footer at the first occurrence of "directory-footer", it made it possible to fool the parsing algorithm into accepting unsigned data at the end of a consensus or vote. This patch fixes that bug by treating the footer as starting with the first "directory-footer" or the first "directory-signature", whichever comes first.
This commit is contained in:
parent
1c25077b1c
commit
27a8a56e6c
@ -5,7 +5,9 @@ Changes in version 0.2.2.10-alpha - 2010-??-??
|
|||||||
and Guard+Exit flagged nodes for entry, middle, and exit positions.
|
and Guard+Exit flagged nodes for entry, middle, and exit positions.
|
||||||
This should more evenly distribute the network load across these
|
This should more evenly distribute the network load across these
|
||||||
different types of nodes, and give us the flexibility to globally
|
different types of nodes, and give us the flexibility to globally
|
||||||
alter our node selection algorithms in the future.
|
alter our node selection algorithms in the future. Extra thanks
|
||||||
|
to "outofwords" for finding some nasty security bugs in the
|
||||||
|
first implementation of this.
|
||||||
|
|
||||||
o Minor features (performance):
|
o Minor features (performance):
|
||||||
- Always perform router selections using weighted node bandwidth,
|
- Always perform router selections using weighted node bandwidth,
|
||||||
|
@ -114,6 +114,7 @@ typedef enum {
|
|||||||
K_CONSENSUS_METHODS,
|
K_CONSENSUS_METHODS,
|
||||||
K_CONSENSUS_METHOD,
|
K_CONSENSUS_METHOD,
|
||||||
K_LEGACY_DIR_KEY,
|
K_LEGACY_DIR_KEY,
|
||||||
|
K_DIRECTORY_FOOTER,
|
||||||
|
|
||||||
A_PURPOSE,
|
A_PURPOSE,
|
||||||
A_LAST_LISTED,
|
A_LAST_LISTED,
|
||||||
@ -488,8 +489,9 @@ static token_rule_t networkstatus_consensus_token_table[] = {
|
|||||||
/** List of tokens allowable in the footer of v1/v2 directory/networkstatus
|
/** List of tokens allowable in the footer of v1/v2 directory/networkstatus
|
||||||
* footers. */
|
* footers. */
|
||||||
static token_rule_t networkstatus_vote_footer_token_table[] = {
|
static token_rule_t networkstatus_vote_footer_token_table[] = {
|
||||||
T01("bandwidth-weights", K_BW_WEIGHTS, ARGS, NO_OBJ ),
|
T01("directory-footer", K_DIRECTORY_FOOTER, NO_ARGS, NO_OBJ ),
|
||||||
T( "directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
|
T01("bandwidth-weights", K_BW_WEIGHTS, ARGS, NO_OBJ ),
|
||||||
|
T( "directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
|
||||||
END_OF_TABLE
|
END_OF_TABLE
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1878,26 +1880,23 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string)
|
|||||||
static INLINE const char *
|
static INLINE const char *
|
||||||
find_start_of_next_routerstatus(const char *s)
|
find_start_of_next_routerstatus(const char *s)
|
||||||
{
|
{
|
||||||
const char *eos = strstr(s, "\nr ");
|
const char *eos, *footer, *sig;
|
||||||
if (eos) {
|
if ((eos = strstr(s, "\nr ")))
|
||||||
const char *eos2 = tor_memstr(s, eos-s, "\ndirectory-footer\n");
|
++eos;
|
||||||
if (eos2) eos2 += strlen("\ndirectory-footer");
|
else
|
||||||
else eos2 = tor_memstr(s, eos-s, "\ndirectory-signature");
|
eos = s + strlen(s);
|
||||||
/* Technically we are returning either the start of the next
|
|
||||||
* routerstatus AFTER the \n, or the start of the next consensus
|
footer = tor_memstr(s, eos-s, "\ndirectory-footer");
|
||||||
* line AT the \n. This seems asymmetric, but leaving it that way
|
sig = tor_memstr(s, eos-s, "\ndirectory-signature");
|
||||||
* for now for stability. */
|
|
||||||
if (eos2 && eos2 < eos)
|
if (footer && sig)
|
||||||
return eos2;
|
return MIN(footer, sig) + 1;
|
||||||
else
|
else if (footer)
|
||||||
return eos+1;
|
return footer+1;
|
||||||
} else {
|
else if (sig)
|
||||||
if ((eos = strstr(s, "\ndirectory-footer\n")))
|
return sig+1;
|
||||||
return eos+strlen("\ndirectory-footer\n");
|
else
|
||||||
if ((eos = strstr(s, "\ndirectory-signature")))
|
return eos;
|
||||||
return eos+1;
|
|
||||||
return s + strlen(s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Given a string at *<b>s</b>, containing a routerstatus object, and an
|
/** Given a string at *<b>s</b>, containing a routerstatus object, and an
|
||||||
@ -3092,6 +3091,13 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
|
|||||||
} SMARTLIST_FOREACH_END(_tok);
|
} SMARTLIST_FOREACH_END(_tok);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((tok = find_opt_by_keyword(footer_tokens, K_DIRECTORY_FOOTER))) {
|
||||||
|
if (tok != smartlist_get(footer_tokens, 0)) {
|
||||||
|
log_warn(LD_DIR, "Misplaced directory-footer token");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tok = find_opt_by_keyword(footer_tokens, K_BW_WEIGHTS);
|
tok = find_opt_by_keyword(footer_tokens, K_BW_WEIGHTS);
|
||||||
if (tok) {
|
if (tok) {
|
||||||
ns->weight_params = smartlist_create();
|
ns->weight_params = smartlist_create();
|
||||||
|
Loading…
Reference in New Issue
Block a user