Commit Graph

32 Commits

Author SHA1 Message Date
Nick Mathewson
cde5c9d0c3 Merge branch 'maint-0.3.3' 2018-05-22 13:35:33 -04:00
Nick Mathewson
a5d4ce2b39 Make the TROVE-2018-005 fix work with rust. 2018-05-22 13:35:20 -04:00
Nick Mathewson
6442417fde fix wide lines 2018-05-22 12:32:00 -04:00
Isis Lovecruft
056be68b1b protover: TROVE-2018-005 Fix potential DoS in protover protocol parsing.
In protover.c, the `expand_protocol_list()` function expands a `smartlist_t` of
`proto_entry_t`s to their protocol name concatenated with each version number.
For example, given a `proto_entry_t` like so:

    proto_entry_t *proto = tor_malloc(sizeof(proto_entry_t));
    proto_range_t *range = tor_malloc_zero(sizeof(proto_range_t));

    proto->name = tor_strdup("DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa");
    proto->ranges = smartlist_new();

    range->low = 1;
    range->high = 65536;

    smartlist_add(proto->ranges, range);

(Where `[19KB]` is roughly 19KB of `"a"` bytes.)  This would expand in
`expand_protocol_list()` to a `smartlist_t` containing 65536 copies of the
string, e.g.:

    "DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=1"
    "DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=2"
    […]
    "DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=65535"

Thus constituting a potential resource exhaustion attack.

The Rust implementation is not subject to this attack, because it instead
expands the above string into a `HashMap<String, HashSet<u32>` prior to #24031,
and a `HashMap<UnvalidatedProtocol, ProtoSet>` after).  Neither Rust version is
subject to this attack, because it only stores the `String` once per protocol.
(Although a related, but apparently of too minor impact to be usable, DoS bug
has been fixed in #24031. [0])

[0]: https://bugs.torproject.org/24031

 * ADDS hard limit on protocol name lengths in protover.c and checks in
   parse_single_entry() and expand_protocol_list().
 * ADDS tests to ensure the bug is caught.
 * FIXES #25517: https://bugs.torproject.org/25517
2018-05-22 12:28:33 -04:00
Nick Mathewson
a3a8d80beb Merge branch 'trove-2018-005_032' into trove-2018-005_033 2018-05-22 12:27:15 -04:00
Isis Lovecruft
eb96692842 protover: TROVE-2018-005 Fix potential DoS in protover protocol parsing.
In protover.c, the `expand_protocol_list()` function expands a `smartlist_t` of
`proto_entry_t`s to their protocol name concatenated with each version number.
For example, given a `proto_entry_t` like so:

    proto_entry_t *proto = tor_malloc(sizeof(proto_entry_t));
    proto_range_t *range = tor_malloc_zero(sizeof(proto_range_t));

    proto->name = tor_strdup("DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa");
    proto->ranges = smartlist_new();

    range->low = 1;
    range->high = 65536;

    smartlist_add(proto->ranges, range);

(Where `[19KB]` is roughly 19KB of `"a"` bytes.)  This would expand in
`expand_protocol_list()` to a `smartlist_t` containing 65536 copies of the
string, e.g.:

    "DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=1"
    "DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=2"
    […]
    "DoSaaaaaaaaaaaaaaaaaaaaaa[19KB]aaa=65535"

Thus constituting a potential resource exhaustion attack.

The Rust implementation is not subject to this attack, because it instead
expands the above string into a `HashMap<String, HashSet<u32>` prior to #24031,
and a `HashMap<UnvalidatedProtocol, ProtoSet>` after).  Neither Rust version is
subject to this attack, because it only stores the `String` once per protocol.
(Although a related, but apparently of too minor impact to be usable, DoS bug
has been fixed in #24031. [0])

[0]: https://bugs.torproject.org/24031

 * ADDS hard limit on protocol name lengths in protover.c and checks in
   parse_single_entry() and expand_protocol_list().
 * ADDS tests to ensure the bug is caught.
 * FIXES #25517: https://bugs.torproject.org/25517
2018-05-22 12:12:01 -04:00
Isis Lovecruft
6739a69c59
tests: Run all existing protover tests in both languages.
There's now no difference in these tests w.r.t. the C or Rust: both
fail miserably (well, Rust fails with nice descriptive errors, and C
gives you a traceback, because, well, C).
2018-04-02 19:59:14 +00:00
Isis Lovecruft
f769edd148
tests: Make inline comments in test_protover.c more accurate.
The DoS potential is slightly higher in C now due to some differences to the
Rust code, see the C_RUST_DIFFERS tags in src/rust/protover/tests/protover.rs.

Also, the comment about "failing at the splitting stage" in Rust wasn't true,
since when we split, we ignore empty chunks (e.g. "1--1" parses into
"(1,None),(None,1)" and "None" can't be parsed into an integer).

Finally, the comment about "Rust seems to experience an internal error" is only
true in debug mode, where u32s are bounds-checked at runtime.  In release mode,
code expressing the equivalent of this test will error with
`Err(ProtoverError::Unparseable)` because 4294967295 is too large.
2018-04-02 19:59:13 +00:00
Isis Lovecruft
ad369313f8
protover: Change protover_all_supported() to return only unsupported.
Previously, if "Link=1-5" was supported, and you asked protover_all_supported()
(or protover::all_supported() in Rust) if it supported "Link=3-999", the C
version would return "Link=3-999" and the Rust would return "Link=6-999".  These
both behave the same now, i.e. both return "Link=6-999".
2018-04-02 19:59:12 +00:00
Isis Lovecruft
527a239863
tests: Run all existing protover tests in both languages.
There's now no difference in these tests w.r.t. the C or Rust: both
fail miserably (well, Rust fails with nice descriptive errors, and C
gives you a traceback, because, well, C).
2018-04-02 19:20:38 +00:00
Isis Lovecruft
22c65a0e4b
tests: Make inline comments in test_protover.c more accurate.
The DoS potential is slightly higher in C now due to some differences to the
Rust code, see the C_RUST_DIFFERS tags in src/rust/protover/tests/protover.rs.

Also, the comment about "failing at the splitting stage" in Rust wasn't true,
since when we split, we ignore empty chunks (e.g. "1--1" parses into
"(1,None),(None,1)" and "None" can't be parsed into an integer).

Finally, the comment about "Rust seems to experience an internal error" is only
true in debug mode, where u32s are bounds-checked at runtime.  In release mode,
code expressing the equivalent of this test will error with
`Err(ProtoverError::Unparseable)` because 4294967295 is too large.
2018-04-02 19:20:37 +00:00
Isis Lovecruft
6e353664dd
protover: Change protover_all_supported() to return only unsupported.
Previously, if "Link=1-5" was supported, and you asked protover_all_supported()
(or protover::all_supported() in Rust) if it supported "Link=3-999", the C
version would return "Link=3-999" and the Rust would return "Link=6-999".  These
both behave the same now, i.e. both return "Link=6-999".
2018-04-02 19:20:36 +00:00
Nick Mathewson
f7eff2f8c5 Merge branch 'maint-0.3.2' into maint-0.3.3 2018-03-01 16:10:43 -05:00
Nick Mathewson
d01abb9346 Merge branch 'maint-0.3.1' into maint-0.3.2 2018-03-01 16:07:59 -05:00
Nick Mathewson
d4a758e083 Merge branch 'maint-0.2.9' into maint-0.3.1 2018-03-01 16:07:59 -05:00
Nick Mathewson
c1bb8836ff Protover tests: disable some obsoleted tests
These were meant to demonstrate old behavior, or old rust behavior.

One of them _should_ work in Rust, but won't because of
implementation details.  We'll fix that up later.
2018-03-01 16:05:17 -05:00
Nick Mathewson
1fe0bae508 Forbid UINT32_MAX as a protocol version
The C code and the rust code had different separate integer overflow
bugs here.  That suggests that we're better off just forbidding this
pathological case.

Also, add tests for expected behavior on receiving a bad protocol
list in a consensus.

Fixes another part of 25249.
2018-03-01 16:05:17 -05:00
Nick Mathewson
8b405c609e Forbid "-0" as a protocol version.
Fixes part of 24249; bugfix on 0.2.9.4-alpha.
2018-03-01 16:05:17 -05:00
Nick Mathewson
0953c43c95 Add more of Teor's protover tests.
These are as Teor wrote them; I've disabled the ones that don't pass
yet, with XXXX comments.
2018-03-01 16:05:17 -05:00
Nick Mathewson
d3a1bdbf56 Add some protover vote round-trip tests from Teor.
I've refactored these to be a separate function, to avoid tricky
merge conflicts.

Some of these are disabled with "XXXX" comments; they should get
fixed moving forward.
2018-03-01 16:05:17 -05:00
teor
8bb79ca4a7
Add unit tests for supported protocols
Prevents future regressions like #25070.
2018-01-30 02:20:30 +11:00
Nick Mathewson
0626031564 Merge branch 'ticket20895' 2017-11-09 09:17:53 -05:00
Chelsea Holland Komlo
d1820c1516 rust implementation of protover 2017-10-27 10:02:08 -04:00
Nick Mathewson
362bc880b1 Add a function to check for support for "protocol X or later"
Also, add unit tests for this new function and for the regular
"does this list include support for protocol X" code.
2017-09-11 09:50:31 -04:00
Nick Mathewson
011d94fb11 apply ahf's test_assert_null.cocci 2017-08-24 15:55:27 -04:00
Nick Mathewson
7505f452c8 Run the copyright update script. 2017-03-15 16:13:17 -04:00
Nick Mathewson
3a3120819c Rename compute_protover_vote to protover_compute_vote 2016-09-26 10:56:53 -07:00
Nick Mathewson
e402cddefe Clean whitespace, add missing documentation 2016-09-26 10:56:52 -07:00
Nick Mathewson
a232161f7b Cover the error cases of parsing protocol versions
Also, detect an additional failure type. Thanks, tests!

(How distinctly I recall thee)
2016-09-26 10:56:50 -07:00
Nick Mathewson
0697e413ef Unit tests for protover_all_supported 2016-09-26 10:56:49 -07:00
Nick Mathewson
c1be8f9d57 Basic backend for the protocol-versions voting algorithm.
[This is a brute-force method that potentially uses way too much
RAM. Need to rethink this a little. Right now you can DOS an
authority by saying "Foo=1-4294967295".]
2016-09-26 10:56:49 -07:00
Nick Mathewson
b2b2e1c7f2 checkpoint basic protover backend 2016-09-26 10:56:48 -07:00