Commit Graph

127 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
Isis Lovecruft 701c2b69f5 rust: Mirror TROVE-2018-005 fix in Rust protover implementation.
* REFACTORS `UnvalidatedProtoEntry::from_str` to place the bulk of the
   splitting/parsing logic in to a new
   `UnvalidatedProtoEntry::parse_protocol_and_version_str()` method (so that
   both `from_str()` and `from_str_any_len()` can call it.)
 * ADD a new `UnvalidatedProtoEntry::from_str_any_len()` method in order to
   maintain compatibility with consensus methods older than 29.
 * ADD a limit on the number of characters in a protocol name.
 * FIXES part of #25517: https://bugs.torproject.org/25517
2018-05-22 12:28:33 -04:00
Isis Lovecruft 569b4e57e2 rust: Mirror TROVE-2018-005 fix in Rust protover implementation.
* REFACTORS `UnvalidatedProtoEntry::from_str` to place the bulk of the
   splitting/parsing logic in to a new
   `UnvalidatedProtoEntry::parse_protocol_and_version_str()` method (so that
   both `from_str()` and `from_str_any_len()` can call it.)
 * ADD a new `UnvalidatedProtoEntry::from_str_any_len()` method in order to
   maintain compatibility with consensus methods older than 29.
 * ADD a limit on the number of characters in a protocol name.
 * FIXES part of #25517: https://bugs.torproject.org/25517
2018-05-22 12:27:25 -04:00
Nick Mathewson 1442e818b6 Merge remote-tracking branch 'isis-github/bug26106' 2018-05-16 09:16:04 -04:00
Nick Mathewson e5974e5158 Merge remote-tracking branch 'isis-github/bug26108' 2018-05-16 09:14:13 -04:00
Isis Lovecruft 4d349c6a61
rust: Update rand_core dependency to 0.2.0-pre.0. 2018-05-15 19:33:20 +00:00
Isis Lovecruft 760cf8e28f
rust: Update rand dev-dependency to 0.5.0-pre.2. 2018-05-15 19:31:29 +00:00
Isis Lovecruft 4c21d41407
rust: Export digests subcrate from our crypto crate. 2018-05-15 18:05:52 +00:00
Isis Lovecruft d9c877a6e5
rust: Export crypto_rand::* functions from our external crate. 2018-05-15 18:03:18 +00:00
Isis Lovecruft 9988882c63
rust: Move rand crate into crypto parent crate. 2018-05-15 17:48:57 +00:00
Isis Lovecruft 2ac849da36
rust: Make Rng::new() methods public. 2018-05-15 17:45:09 +00:00
Isis Lovecruft af182d4ab5
rust: Add crypto crate and implement Rust wrappers for SHA2 code.
* FIXES #24659: https://bugs.torproject.org/24659
2018-05-08 21:03:37 +00:00
Isis Lovecruft f36656cada
build: Fix missing include for src/rust/external/crypto_rand.rs file.
* FIXES #26025: https://bugs.torproject.org/26025
2018-05-04 22:23:17 +00:00
Isis Lovecruft f1864ff4a1
rust: Update Cargo.lock file with changes from #26024. 2018-05-04 20:41:25 +00:00
Isis Lovecruft b5bd19ea05
Update rand dependency from 0.5.0-pre.0 to 0.5.0-pre.1. 2018-05-04 19:16:42 +00:00
Nick Mathewson 6f8b961a65 I should have tested before I pushed. 2018-05-03 20:16:53 -04:00
Nick Mathewson 2f269bfaf1 Add src/rust/rand to include.am 2018-05-03 16:16:09 -04:00
Nick Mathewson c3b7258370 Merge remote-tracking branch 'isis/bug24660_r1' 2018-05-03 13:50:18 -04:00
Isis Lovecruft 94dcd38a14
rust: Expose crypto_rand() as an impl of rand_core::RngCore. 2018-05-02 22:12:38 +00:00
Isis Lovecruft b5013e841c
rust: Remove mirrored PRNG implementation.
Once we need a PRNG, we'll likely want to change the dev-dependency on the rand
crate to be a real dependency, and use rand::SmallRng as our PRNG.
2018-04-20 23:54:48 +00:00
Isis Lovecruft 49639b2826
rust: Expose our (P)RNGs in Rust and provide safe wrappers.
* FIXES #24660: https://bugs.torproject.org/24660
2018-04-20 23:54:47 +00:00
Nick Mathewson 2fac948158 Include tor_log rust files in source distribution.
Fixes another case of #25732; bug not in any released Tor.
2018-04-06 16:19:14 -04:00
Nick Mathewson fb2fe41f6f Merge branch 'maint-0.3.3' 2018-04-06 16:18:47 -04:00
Nick Mathewson 306563ac68 Ship all files needed to build Tor with rust
Fixes bug 25732; bugfix on 0.3.3.2-alpha when strings.rs was
introduced.
2018-04-06 16:18:11 -04:00
Isis Lovecruft c65088cb19
rust: Fix ProtoSet and ProtoEntry to use the same DoS limits as C.
Previously, the limit for MAX_PROTOCOLS_TO_EXPAND was actually being applied
in Rust to the maximum number of version (total, for all subprotocols).
Whereas in C, it was being applied to the number of subprotocols that were
allowed.  This changes the Rust to match C's behaviour.
2018-04-02 19:59:16 +00:00
Isis Lovecruft 4b4e36a413
rust: Port all C protover_all_supported tests to Rust.
The behaviours still do not match, unsurprisingly, but now we know where a
primary difference is: the Rust is validating version ranges more than the C,
so in the C it's possible to call protover_all_supported on a ridiculous
version range like "Sleen=0-4294967294" because the C uses
MAX_PROTOCOLS_TO_EXPAND to count the number of *subprotocols* whereas the Rust
uses it to count the total number of *versions* of all subprotocols.
2018-04-02 19:59:15 +00:00
Isis Lovecruft cd28b4c7f5
rust: Refactor protover::compute_for_old_tor().
During code review and discussion with Chelsea Komlo, she pointed out
that protover::compute_for_old_tor() was a public function whose
return type was `&'static CStr`.  We both agree that C-like parts of
APIs should:

1. not be exposed publicly (to other Rust crates),
2. only be called in the appropriate FFI code,
3. not expose types which are meant for FFI code (e.g. `*mut char`,
   `CString`, `*const c_int`, etc.) to the pure-Rust code of other
   crates.
4. FFI code (e.g. things in `ffi.rs` modules) should _never_ be called
   from pure-Rust, not even from other modules in its own crate
   (i.e. do not call `protover::ffi::*` from anywhere in
   `protover::protoset::*`, etc).

With that in mind, this commit makes the following changes:

 * CHANGE `protover::compute_for_old_tor()` to be
   visible only at the `pub(crate)` level.
 * RENAME `protover::compute_for_old_tor()` to
   `protover::compute_for_old_tor_cstr()` to reflect the last change.
 * ADD a new `protover::compute_for_old_tor()` function wrapper which
   is public and intended for other Rust code to use, which returns a
   `&str`.
2018-04-02 19:59:12 +00:00
Isis Lovecruft fd127bfbfa
rust: Refactor Rust implementation of protover_is_supported_here().
It was changed to take borrows instead of taking ownership.

 * REFACTOR `protover::ffi::protover_is_supported_here()` to use changed method
   signature on `protover::is_supported_here()`.
2018-04-02 19:36:26 +00:00
Isis Lovecruft 32638ed4a6
rust: Refactor Rust impl of protover_compute_vote().
This includes a subtle difference in behaviour to the previous Rust
implementation, where, for each vote that we're computing over, if a single one
fails to parse, we skip it.  This now matches the current behaviour in the C
implementation.

 * REFACTOR `protover::ffi::protover_compute_vote()` to use
   new types and methods.
2018-04-02 19:36:25 +00:00
Isis Lovecruft 269053a380
rust: Refactor Rust impl of protover_list_supports_protocol_or_later().
This includes a subtle difference in behaviour, as in 4258f1e18, where we return
(matching the C impl's return behaviour) earlier than before if parsing failed,
saving us computation in parsing the versions into a
protover::protoset::ProtoSet.

 * REFACTOR `protover::ffi::protover_list_supports_protocol_or_later()` to use
   new types and methods.
2018-04-02 19:36:25 +00:00
Isis Lovecruft 63eeda89ea
rust: Refactor Rust impl of protover_list_supports_protocol().
This includes a subtle difference in behaviour, as in 4258f1e18, where we return
(matching the C impl's return behaviour) earlier than before if parsing failed,
saving us computation in parsing the versions into a
protover::protoset::ProtoSet.

 * REFACTOR `protover::ffi::protover_list_supports_protocol()` to use new types
   and methods.
2018-04-02 19:34:26 +00:00
Isis Lovecruft c7bcca0233
rust: Refactor Rust impl of protover_all_supported().
This includes differences in behaviour to before, which should now more closely
match the C version:

 - If parsing a protover `char*` from C, and the string is not parseable, this
   function will return 1 early, which matches the C behaviour when protocols
   are unparseable.  Previously, we would parse it and its version numbers
   simultaneously, i.e. there was no fail early option, causing us to spend more
   time unnecessarily parsing versions.

 * REFACTOR `protover::ffi::protover_all_supported()` to use new types and
   methods.
2018-04-02 19:34:26 +00:00
Isis Lovecruft 493e565226
rust: Refactor protover tests with new methods; note altered behaviours.
Previously, the rust implementation of protover considered an empty string to be
a valid ProtoEntry, while the C version did not (it must have a "=" character).
Other differences include that unknown protocols must now be parsed as
`protover::UnknownProtocol`s, and hence their entries as
`protover::UnvalidatedProtoEntry`s, whereas before (nearly) all protoentries
could be parsed regardless of how erroneous they might be considered by the C
version.

My apologies for this somewhat messy and difficult to read commit, if any part
is frustrating to the reviewer, please feel free to ask me to split this into
smaller changes (possibly hard to do, since so much changed), or ask me to
comment on a specific line/change and clarify how/when the behaviours differ.

The tests here should more closely match the behaviours exhibited by the C
implementation, but I do not yet personally guarantee they match precisely.

 * REFACTOR unittests in protover::protover.
 * ADD new integration tests for previously untested behaviour.
 * FIXES part of #24031: https://bugs.torproject.org/24031.
2018-04-02 19:34:25 +00:00
Isis Lovecruft 35b86a12e6
rust: Refactor protover::is_supported_here().
This changes `protover::is_supported_here()` to be aware of new datatypes
(e.g. don't call `.0` on things which are no longer tuple structs) and also
changes the method signature to take borrows, making it faster, threadable, and
easier to read (i.e. the caller can know from reading the function signature
that the function won't mutate values passed into it).

 * CHANGE the `protover::is_supported_here()` function to take borrows.
 * REFACTOR the `protover::is_supported_here()` function to be aware of new
   datatypes.
 * FIXES part of #24031: https://bugs.torproject.org/24031
2018-04-02 19:34:25 +00:00
Isis Lovecruft 2eb1b7f2fd
rust: Add new ProtoverVote type and refactor functions to methods.
This adds a new type for votes upon `protover::ProtoEntry`s (technically, on
`protover::UnvalidatedProtoEntry`s, because the C code does not validate based
upon currently known protocols when voting, in order to maintain
future-compatibility), and converts several functions which would have operated
on this datatype into methods for ease-of-use and readability.

This also fixes a behavioural differentce to the C version of
protover_compute_vote().  The C version of protover_compute_vote() calls
expand_protocol_list() which checks if there would be too many subprotocols *or*
expanded individual version numbers, i.e. more than MAX_PROTOCOLS_TO_EXPAND, and
does this *per vote* (but only in compute_vote(), everywhere else in the C seems
to only care about the number of subprotocols, not the number of individual
versions).  We need to match its behaviour in Rust and ensure we're not allowing
more than it would to get the votes to match.

 * ADD new `protover::ProtoverVote` datatype.
 * REMOVE the `protover::compute_vote()` function and refactor it into an
   equivalent-in-behaviour albeit more memory-efficient voting algorithm based
   on the new underlying `protover::protoset::ProtoSet` datatype, as
   `ProtoverVote::compute()`.
 * REMOVE the `protover::write_vote_to_string()` function, since this
   functionality is now generated by the impl_to_string_for_proto_entry!() macro
   for both `ProtoEntry` and `UnvalidatedProtoEntry` (the latter of which is the
   correct type to return from a voting protocol instance, since the entity
   voting may not know of all protocols being voted upon or known about by other
   voting parties).
 * FIXES part of #24031: https://bugs.torproject.org/24031

rust: Fix a difference in compute_vote() behaviour to C version.
2018-04-02 19:34:24 +00:00
Isis Lovecruft fa15ea104d
rust: Add macro for `impl ToString for {Unvalidated}ProtoEntry`.
This implements conversions from either a ProtoEntry or an UnvalidatedProtoEntry
into a String, for use in replacing such functions as
`protover::write_vote_to_string()`.

 * ADD macro for implementing ToString trait for ProtoEntry and
   UnvalidatedProtoEntry.
 * FIXES part of #24031: https://bugs.torproject.org/24031
2018-04-02 19:34:24 +00:00
Isis Lovecruft 3c47d31e1f
rust: Add new protover::UnvalidatedProtoEntry type.
This adds a new protover::UnvalidatedProtoEntry type, which is the
UnknownProtocol variant of a ProtoEntry, and refactors several functions which
should operate on this type into methods.

This also fixes what was previously another difference to the C implementation:
if you asked the C version of protovet_compute_vote() to compute a single vote
containing "Fribble=", it would return NULL.  However, the Rust version would
return "Fribble=" since it didn't check if the versions were empty before
constructing the string of differences.  ("Fribble=" is technically a valid
protover string.)  This is now fixed, and the Rust version in that case will,
analogous to (although safer than) C returning a NULL, return None.

 * REMOVE internal `contains_only_supported_protocols()` function.
 * REMOVE `all_supported()` function and refactor it into
   `UnvalidatedProtoEntry::all_supported()`.
 * REMOVE `parse_protocols_from_string_with_no_validation()` and
   refactor it into the more rusty implementation of
   `impl FromStr for UnvalidatedProtoEntry`.
 * REMOVE `protover_string_supports_protocol()` and refactor it into
   `UnvalidatedProtoEntry::supports_protocol()`.
 * REMOVE `protover_string_supports_protocol_or_later()` and refactor
   it into `UnvalidatedProtoEntry::supports_protocol_or_later()`.
 * FIXES part of #24031: https://bugs.torproject.org/24031

rust: Fix another C/Rust different in compute_vote().

This fixes the unittest from the prior commit by checking if the versions are
empty before adding a protocol to a vote.
2018-04-02 19:34:23 +00:00
Isis Lovecruft 54c964332b
rust: Add new protover::ProtoEntry type which uses new datatypes.
This replaces the `protover::SupportedProtocols` (why would you have a type just
for things which are supported?) with a new, more generic type,
`protover::ProtoEntry`, which utilises the new, more memory-efficient datatype
in protover::protoset.

 * REMOVE `get_supported_protocols()` and `SupportedProtocols::tor_supported()`
   (since they were never used separately) and collapse their functionality into
   a single `ProtoEntry::supported()` method.
 * REMOVE `SupportedProtocols::from_proto_entries()` and reimplement its
   functionality as the more rusty `impl FromStr for ProtoEntry`.
 * REMOVE `get_proto_and_vers()` function and refactor it into the more rusty
   `impl FromStr for ProtoEntry`.
 * FIXES part of #24031: https://bugs.torproject.org/24031
2018-04-02 19:32:36 +00:00
Isis Lovecruft 60daaa68b1
rust: Add new protover::UnknownProtocol type.
* ADD new type, protover::UnknownProtocol, so that we have greater type safety
   and our protover functionality which works with unsanitised protocol names is
   more clearly demarcated.
 * REFACTOR protover::Proto, renaming it protover::Protocol to mirror the new
   protover::UnknownProtocol type name.
 * ADD a utility conversion of `impl From<Protocol> for UnknownProtocol` so that
   we can easily with known protocols and unknown protocols simultaneously
   (e.g. doing comparisons, checking their version numbers), while not allowing
   UnknownProtocols to be accidentally used in functions which should only take
   Protocols.
 * FIXES part of #24031: https://bugs.torproject.org/24031
2018-04-02 19:27:51 +00:00
Isis Lovecruft e6625113c9
rust: Implement more memory-efficient protover datatype.
* ADD new protover::protoset module.
 * ADD new protover::protoset::ProtoSet class for holding protover versions.
 * REMOVE protover::Versions type implementation and its method
   `from_version_string()`, and instead implement this behaviour in a more
   rust-like manner as `impl FromStr for ProtoSet`.
 * MOVE the `find_range()` utility function from protover::protover to
   protover::protoset since it's only used internally in the
   implementation of ProtoSet.
 * REMOVE the `contract_protocol_list()` function from protover::protover and
   instead refactor it (reusing nearly the entire thing, with minor superficial,
   i.e. non-behavioural, changes) into a more rusty
   `impl ToString for ProtoSet`.
 * REMOVE the `expand_version_range()` function from protover::protover and
   instead refactor it into a more rusty implementation of
   `impl Into<Vec<Version>> for ProtoSet` using the new error types in
   protover::errors.
 * FIXES part of #24031: https://bugs.torproject.org/24031.
2018-04-02 19:26:26 +00:00
Isis Lovecruft 88204f91df
rust: Implement error types for Rust protover implementation.
This will allow us to do actual error handling intra-crate in a more
rusty manner, e.g. propogating errors in match statements, conversion
between error types, logging messages, etc.

 * FIXES part of #24031: https://bugs.torproject.org/24031.
2018-04-02 19:24:32 +00:00
Isis Lovecruft f2daf82794
rust: Fix ProtoSet and ProtoEntry to use the same DoS limits as C.
Previously, the limit for MAX_PROTOCOLS_TO_EXPAND was actually being applied
in Rust to the maximum number of version (total, for all subprotocols).
Whereas in C, it was being applied to the number of subprotocols that were
allowed.  This changes the Rust to match C's behaviour.
2018-04-02 19:20:40 +00:00
Isis Lovecruft 6eea0dc5f1
rust: Port all C protover_all_supported tests to Rust.
The behaviours still do not match, unsurprisingly, but now we know where a
primary difference is: the Rust is validating version ranges more than the C,
so in the C it's possible to call protover_all_supported on a ridiculous
version range like "Sleen=0-4294967294" because the C uses
MAX_PROTOCOLS_TO_EXPAND to count the number of *subprotocols* whereas the Rust
uses it to count the total number of *versions* of all subprotocols.
2018-04-02 19:20:39 +00:00
Isis Lovecruft fc2a42cc49
rust: Refactor protover::compute_for_old_tor().
During code review and discussion with Chelsea Komlo, she pointed out
that protover::compute_for_old_tor() was a public function whose
return type was `&'static CStr`.  We both agree that C-like parts of
APIs should:

1. not be exposed publicly (to other Rust crates),
2. only be called in the appropriate FFI code,
3. not expose types which are meant for FFI code (e.g. `*mut char`,
   `CString`, `*const c_int`, etc.) to the pure-Rust code of other
   crates.
4. FFI code (e.g. things in `ffi.rs` modules) should _never_ be called
   from pure-Rust, not even from other modules in its own crate
   (i.e. do not call `protover::ffi::*` from anywhere in
   `protover::protoset::*`, etc).

With that in mind, this commit makes the following changes:

 * CHANGE `protover::compute_for_old_tor()` to be
   visible only at the `pub(crate)` level.
 * RENAME `protover::compute_for_old_tor()` to
   `protover::compute_for_old_tor_cstr()` to reflect the last change.
 * ADD a new `protover::compute_for_old_tor()` function wrapper which
   is public and intended for other Rust code to use, which returns a
   `&str`.
2018-04-02 19:20:36 +00:00
Isis Lovecruft 9766d53cf9
rust: Refactor Rust implementation of protover_is_supported_here().
It was changed to take borrows instead of taking ownership.

 * REFACTOR `protover::ffi::protover_is_supported_here()` to use changed method
   signature on `protover::is_supported_here()`.
2018-04-02 19:20:35 +00:00
Isis Lovecruft 6f252e0986
rust: Refactor Rust impl of protover_compute_vote().
This includes a subtle difference in behaviour to the previous Rust
implementation, where, for each vote that we're computing over, if a single one
fails to parse, we skip it.  This now matches the current behaviour in the C
implementation.

 * REFACTOR `protover::ffi::protover_compute_vote()` to use
   new types and methods.
2018-04-02 19:20:34 +00:00
Isis Lovecruft 0a5494b81d
rust: Refactor Rust impl of protover_list_supports_protocol_or_later().
This includes a subtle difference in behaviour, as in 4258f1e18, where we return
(matching the C impl's return behaviour) earlier than before if parsing failed,
saving us computation in parsing the versions into a
protover::protoset::ProtoSet.

 * REFACTOR `protover::ffi::protover_list_supports_protocol_or_later()` to use
   new types and methods.
2018-04-02 19:20:33 +00:00
Isis Lovecruft 52c3ea5045
rust: Refactor Rust impl of protover_list_supports_protocol().
This includes a subtle difference in behaviour, as in 4258f1e18, where we return
(matching the C impl's return behaviour) earlier than before if parsing failed,
saving us computation in parsing the versions into a
protover::protoset::ProtoSet.

 * REFACTOR `protover::ffi::protover_list_supports_protocol()` to use new types
   and methods.
2018-04-02 19:20:32 +00:00
Isis Lovecruft 2f3a7376c0
rust: Refactor Rust impl of protover_all_supported().
This includes differences in behaviour to before, which should now more closely
match the C version:

 - If parsing a protover `char*` from C, and the string is not parseable, this
   function will return 1 early, which matches the C behaviour when protocols
   are unparseable.  Previously, we would parse it and its version numbers
   simultaneously, i.e. there was no fail early option, causing us to spend more
   time unnecessarily parsing versions.

 * REFACTOR `protover::ffi::protover_all_supported()` to use new types and
   methods.
2018-04-02 19:20:31 +00:00