Previously, we'd only call PendingNetDir::upgrade_if_necesessary
when adding a microdescriptor. But if it began already having all
of its descriptors (because we found them in the cache), we wouldn't
actually upgrade it to a PendingNetDir::Yielding, which would make
it unusable, and would make us schedule its reset time too far
in the future.
Fixes#802.
We will use this for a lack of HS directories. (These aren't chosen
according to any local restrictions, so the problems with EK::NoPath
and EK::NoExit don't arise.)
Fixes
cargo +stable test --locked --offline F -p tor-netdoc
cargo +stable clippy -p tor-netdoc F --all-targets
for values of F including
--all-features
--features=hs-client
--features=hs-common
--features=hs-service
(nothing)
I couldn't find a test vector in C Tor. This test case was generated
from the code here.
I'm fairly sure it's right since I managed to get my descriptor
downloader to work. (That's not an MR yet, but uses this code.)
So far these are just the errors that occur during descriptor
fetch. There will be more later as we have more code in tor-hsconn.
This is very user-facing; use the "onion service" terminology.
Previously, to build descriptors for hidden services with client auth
enabled, in addition to the list of authorized clients, users of
`HsDescBuilder` were required to also provide a descriptor encryption
keypair and a descriptor cookie. This was potentially dangerous and/or
error-prone, because the ephemeral encryption key and the descriptor
cookie are expected to be randomly generated and unique for each
descriptor.
This change makes `ClientAuth` private to the `hsdesc::build` module and
updates `HsDescBuilder` to build `ClientAuth`s internally. Users now
only need to provide the list of authorized client public keys.
Signed-off-by: Gabriela Moldovan <gabi@torproject.org>
This adds a test for an `encode -> decode -> encode` flow for a hidden
service descriptor with client authorization enabled.
Signed-off-by: Gabriela Moldovan <gabi@torproject.org>
`AuthClient`s were originally meant to represent parsed `auth-client`
lines. In !1070, this struct was repurposed for representing individual
authorized clients in the HS descriptor encoder. However, hidden
services will likely use a list of public keys to represent the
authorized clients rather than a list of `AuthClient`s, as the
information from an `AuthClient` (`client_id`, `iv`, `encrypted_cookie`)
likely won't be immediately available to the hidden service.
This change updates the HS descriptor encoder to represent authorized
clients as a list of `curve25519::PublicKey`s. As such, it is now the
responsibility of the encoder to create the `client_id`, `iv`, and
`encrypted_cookie` using the available keys, the unencrypted descriptor
cookie, and HS subcredential.
Signed-off-by: Gabriela Moldovan <gabi@torproject.org>
These crates had no changes until just a moment ago. But since
we updated the versions on some of their dependents, they have now
changed themselves. Thus they get patchlevel bumps.
```
tor-rtmock
tor-protover
tor-socksproto
tor-consdiff
tor-chanmgr
tor-dirclient
tor-hsservice
```
For these crates, the changes are nontrivial, so we
_do_ bump the versions on which their dependent crates depend.
Fortunately, since they are all pre-1.0, we don't need to
distinguish semver-additions from other changes. (Except for arti,
which _is_ post-1.0, but gets a patchlevel bump anyway.)
These are unstable crates with breaking changes:
```
tor-hscrypto
tor-hsclient
```
These have new or extended APIs:
```
safelog
tor-bytes
tor-cell
tor-linkspec
tor-llcrypto
tor-proto
tor-cert
arti-client
```
These have new unstable APIs or features:
```
tor-netdoc
tor-circmgr (also broke some unstable APIs)
arti (is post-1.0)
```
These have bugfixes only:
```
caret
tor-dirmgr
```
Their dependents are _not_ updated to a more recent version.
These bumped the version of a dependency that they don't expose
```
tor-rtcompat
fs-mistrust
```
This one had internal refactoring:
```
tor-netdir
```
These had trivial changes only:
```
tor-checkable
tor-ptmgr
tor-guardmgr
arti-hyper
arti-bench
arti-testing
```
I found that I had the bug where I forgot to call this function, and
reached
bad_api_usage!("The circuit launcher wasn't initialized")
The possibility of such a bug is a hazard of this API pattern.
I don't think the server-side support will want to explicitly call
current and then secondary. Rather, it will want to iterate over all
the relevant ones.
And fix the name, and add another comment about whether we need this.
Change its name to hs_* like we do with things at this layer.
But, it turns out, that at least for hs client connections to fetch
the descriptor, I don't seem to need to call it yet ? Maybe it's not
needed.
* Don't ever use the words "parameter" or "param".
These doesn't appear in the spec anywhere.
* Use `h` as the variable name for the unclamped blinding factor,
and `blinding_factor` in function names.
Unhelpfully, the spec uses the variable name `h` and the phrase
"blinding factor" for both the unclamped and clamped value. The
clamped value is internal to the algorithm.
In our code:
* Don't ever use the word "parameter" or variable name `param`.
This doesn't appear in the spec anywhere.
* Use `h` for the unclamped blinding factor, and `blinding_factor` for the
clamped blinding factor.
* Rename `blinding_factor` function to `clamp_blinding_factor`, since
in the spec's terminology it takes an (unclamped) "blinding factor"
and returns a (clamped) "blinding factor".
* State explicitly what thing in the spec the `h` parameters are.
There are too many things called "index" here. `idx` could be read to
mean the table index `RouterStatusIdx`, the hsdir hash `HsDirIndex`,
or an entry in some other one of these tables.
Here's, it's just the sequence number of the index in the test netdir.
Use `pos` for that. (`seq` would have been another possibility.)
The hidden services directory hashring is a ring of hsdir relays,
sorted by a hash that the spec calls the "index". That's `HsDirIndex`.
This was a bad idea because the word "index" is seriously overused,
but in Arti we must use the same terminology.
At least, qualify it everywhere. Now one of these hsdir sort position
hashes is always, in our code, an `hsdir_index`.
I think this is necessary even inside modules called `hsdir_*`,
because those can deal with other kind of "index" too.
This is an `IndexVec` key type. Some places used `idx`, some `rsi`,
some `rs_idx`.
Use `rsidx` for it everywhere, including in locals, function names,
and fields. `rsidx` is a compromise. `rsi` might be a bit opaque,
but we want a one-"word" name since it appears inside other names.
This fixes a broken doc link I introduced in !1070:
```
error: unresolved link to `crate::doc::hsdesc::build::inner::HsDescInnerBuilder`
--> crates/tor-netdoc/src/doc/hsdesc/build/middle.rs:34:11
|
34 | /// [`crate::doc::hsdesc::build::inner::HsDescInnerBuilder`] as described in sections
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `HsDescInnerBuilder` in module `inner`
|
= note: `-D rustdoc::broken-intra-doc-links` implied by `-D warnings`
error: could not document `tor-netdoc`
```
Signed-off-by: Gabriela Moldovan <gabi@torproject.org>
Hidden services use blinded singing keys derived from the identity key
to sign descriptor signing keys.
Before this patch, the hidden descriptor builder represented its blinded
signing keys (`blinded_id`) as plain `ed25519::Keypair`s. This was not
ideal, as there was nothing preventing the caller from accidentally
initializing `blinded_id` with an unblinded keypair.
This introduces a new `HsBlindKeypair` type to represent blinded
keypairs.
Signed-off-by: Gabriela Moldovan <gabi@torproject.org>
`NetdocText` is a wrapper around a `String` and a type marker. The type
annotation proved of limited use, and made the netdoc builder API
somewhat awkward to use.
Signed-off-by: Gabriela Moldovan <gabi@torproject.org>
Unlike `hsdesc::IntroPointDesc`, `hsdesc::build::IntroPointDesc`
represents link specifiers as `LinkSpec`s rather than
`UnparsedLinkSpec`s.
Since this is a general-purpose representation of an introduction point
and not merely an intermediate representation for decoding/encoding, it
will probably need to be factored out of `tor-netdoc` at some point.
Signed-off-by: Gabriela Moldovan <gabi@torproject.org>
This introduces the `NetdocBuilder` trait described in
`netdoc-builder.md` and a new `tor-netdoc::doc::hsdesc::build` module,
which exports the `HsDescBuilder`. Hidden services will use
`HsDescBuilder` to build and encode hidden service descriptors.
There are several TODOs in the code that I'm planning to address
separately.
Partially addresses #745.
Signed-off-by: Gabriela Moldovan <gabi@torproject.org>
These are used in multiple places (and will also be used by the HS
descriptor encoder later on), so let's make them named constants.
Signed-off-by: Gabriela Moldovan <gabi@torproject.org>
This makes some code a bit more concise, as it allows us to make
`Strings` into `ItemArgument`s without calling `.as_str()`.
Signed-off-by: Gabriela Moldovan <gabi@torproject.org>
We're going to want to reuse this.
Also: rename StreamPrefs::isolation and update the docs, to better
reflect its rather limited functionality. The new
TorClient::isolation is the only call site.
We now have support for a pool of pre-build circuits that we can use
for HS-related purposes, and we take circuits from this pool as
needed.
Nothing populates or cleans the circuit pool yet.
Since we made the internals of the ptmgr protocol parser
conditionally private, we need to tell Cargo to build the fuzzer
with the `experimental-api` feature so that it can access them.
The derive_hash_xor_eq lint was renamed in 1.68, but we can't use
it under its new name, since we still need to support back to 1.60.
Instead, we suppress the warning about the lint being renamed.
(I found "user request" in one place, and fixed that. I am not
currently going to try to unify "control message" and "meta message"
since both terms are misleading and we already have TODOs to try to
merge them into a third better term.)
This new function combines "sending a message" and "accepting
replies in a stream" into a single call, so that there is no gap
between when the message is sent and the replies are available.
There are a number of compromises here, in order to avoid API
proliferation. I've tried to contain them as best I can.
See comments for additional design discussion.
Now, the MetaCellHandler is responsible for consuming the messages
it gets, and reporting status to whatever task is waiting for a
status message.
Additionally, the MetaCellHandler can decide to remain installed or
shut down the circuit after a successful message. (Previously, it
could only uninstall itself on success and kill the circuit on
failure.)
These changes will enable MetaCellHandlers to be used as the basis
for handling more kinds of message.
(There is some moved and reformatted code here; you may want to
review it with `git {diff or show} --color-moved -b`.)
When I was trying to add HS support to these layers, I found I could
add a new variant to the `Host` enum but everything would still
compile even though I hadn't written the necessary implementation!
This method is a liability: when using it, one inevitably writes such
latent bugs.
Doing so doesn't seem like a good idea. It might even be some kind of
leak?
Found because I added a variant to `address::Host` for hidden
services, and noticed that the resolve code still compiled.
Doing this means that any attempt to use a read-only store would
crash as soon as it found that the consensus was usable.
It seems that this bug was introduced at some point doing all the
dirmgr refactors we did over the past year. Perhaps there should be
a test for running with a read-only store.
Fixes#779
Previously, if somebody wrote this code, an attacker could easily
use it to cause an OOM panic:
```
let n = r.take_u64();
let items: Vec<Foo> = r.extract_n(n as usize)?;
```
The first line of defense here is not to write protocols like that:
we don't actually _have_ any 32-bit counters in our protocol
AFAICT.
The second line of defense is to pre-check `n` for reasonableness
before calling `extract_n`.
Here we add a third line of defense: whereas previously we would do
`Vec::with_capacity(n)` in `extract_n`, we now allocate an initial
capacity of `min(n, r.remaining())`. This ensures that the size of
the allocation can't exceed the remaining length of the message,
which (for our cell types at least) should prevent it from
overflowing or running OOM.
These Arcs are all "downward", referencing items from layers lower in
the stack. So they don't cause cycles.
There was going to be a cycle involving the `OnionConnector` upcall
trait, but we have just abolished that.
Abolish CircMgr::get_or_launch_onion_client and everything to support
it. We have decided that `.onion` diversion ccan't/shouldn't occur in
tor-circmgr. Probably, it should occur much higher up - arti-client
maybe - since it will sometimes need ambient authority (KS_hsc_*).
Now all knowledge of HS connections is in tor-hsclient. This
gets rid of a layering inversion and the trait needed for tor-circmgr
to do the upcall to tor-hsclient.
This is getting rather confusing; simply reformtting it won't do, I
think. Also there would be much rightward drift.
So move the meat out into the new function.
(And introduce a convenience alias for its captures.)
Docs and reformatting will follow in a moment.
Explicit drops don't work. Instead, introduce a scope.
We need two scopes, actually: one where we do the initial table
wrangling, and one for the retries after relock.
So we must put the meat in a closure so we can reuse it.
And we must return the flow control as an enum. Bah, etc.
Avoid reformatting this for the moment. This makes the delta legible...
This is still correct from a lock hierarchy pov. It moves the guard
relock to the end, which is going to be necessary since it is going to
have to move right outside the loop.