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>
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.
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...
Provide a more cookied "secret keys for use to connecting to a
particular HS" type, with a builder.
This wants to use config stuff, so oughtn't to be in tor-*crypto.
The individual types remain there.
These crates didn't have any changes until now, when I bumped
the versions of some other crates they depend on:
tor-consdiff
arti-hyper
arti-bench
arti-testing
These crates have had small code changes, but no API additions:
tor-config
tor-socksproto
tor-cert
tor-chanmgr
tor-ptmgr
tor-guardmgr
tor-circmgr
tor-dirclient
tor-dirmgr
arti
tor-hsservice
tor-congestion
These crates have had API extensions:
fs-mistrust
tor-llcrypto
tor-bytes
tor-checkable
tor-linkspec
tor-netdoc
tor-persist
arti-client
These are API breaks, but the crates themselves are currently
100% experimental, so there's no need to bump the minor versions
according to our semver rules.
We now manipulate raw relay cell bodies as (an alias for)
`Box<[u8;509]>` rather than as (an alias for) `[u8;509]`. This
enables us to do much less copying. It will become more important
soon, as we defer parsing relay cell bodies even longer.
Related to #7.
We also use SliceWriter to avoid allocating a Vec<> for every relay
message we want to encode, and instead encode directly into the
cell.
Locally, the only functional effect is that now we refuse to handle
non-whole-number-of-minutes lengths - but since the consensus
parameter can't represent those, there's no overall functional change.
There are some places where I note certificates which are not
currently validated, because there is no cryptographic point in
doing so. We should either document that this is okay, or validate
the certificates anyway.
This code might benefit from refactoring to make it prettier.
In !948 we renamed a couple of accessor functions, which is a
breaking change in `tor-cell`'s API.
In retrospect, perhaps we should have deprecated the old names and
added the new ones, so we wouldn't have to break the API. (This is
the only API break AFAICT since 1.1.0.)
These changes influence behavior, but not effect compatibility.
(If I messed up, and any crate except for `arti` has non-breaking
API changes, that's still fine, since they are all version
0.x.)
This logic is a bit tricky, so I've tried to document it and add
fairly good tests. The silver lining is that the external API for
all of this logic will make it invisible and hidden.
There are some cases where I added functions that I think might
eventually get lowered into MdConsensus: But I don't want to lower
too much right now, since the convention for our netdoc accessors is
that they are fairly unsophisticated, and they show you the document
as it is.
Closes#686
This required rewriting some of our error handling code in
command-line processing, since the toml crate now displays and
reports errors differently. (Admittedly, this code still is kind of
ugly, but at least it is nicely hidden.)
This is in lieu of upgrading to the latest base64 crate, which has
a different API from the old one. Since we have to migrate either
way, we might as well use base64ct everywhere.
I don't think that most of these cases _require_ constant-time
base64, but it won't hurt.
These are a bit complex internally, but the API they present is
pretty simple. I've left some discussion of points where the design
isn't totally fleshed out, and where we need to look harder at the
spec.
Part of #716.
On 1.22, cargo audit is complaining about RUSTSEC-2023-0001.
We aren't affected, since we don't use windows named pipes (yet),
but let's make cargo audit happier.
This module has types and operations needed in multiple places
for an onion service implementation. There are a bunch of
TODO hs-crypto comments that we'll need to fill in.
This is the new upstream version (published by me, recently).
It has the same MSRV and one breaking change:
The caller who specifies a home dir function for substituting into
strings, must now supply a string, not Path. Previously shellexpand
would allow the caller to supply non-unicode data, and then simply not
substitute it. That was an infelicity in the shellexpand API.
Now this infelicity is pushed into our code. The overall behaviour of
Arti hasn't changed as a result. And it seems reasonable to me.
shellexpand 3.x also has a module for expanding Paths instead, in
response to requests for this filed as upstream tickets. We *could*
use that but I am not sanguine about that approach: the Pathness would
spread throughout much of our config and file handling code.
I think we should at the very least postpone trying to work with
invalid-unicode-paths as long as we can.
As near as I can tell, the rust-crypto SHA1 crate was called `sha-1`
for a while because of a conflict with a different SHA1 crate. Now
they apparently have the `sha1` name back and have deprecated the
`sha-1` name.
This makes a `pt_state` directory inside .local/share/arti (or the
local equivalent), right next to our existing `state` dir.
Ideally we would use a separate directory for each PT, but we have a
very fuzzy "what is a specific PT" notion.
Closes#667
These are implementation details and we don't want to mark them as
stable.
To do this, I needed to apply some additional options to the example
code's configuration in Cargo.toml.
This commit implements `PtMgr`, a pluggable transport manager
responsible for keeping track of spawned PTs and spawning them to
satisfy client requests on demand.
It does this in two parts: the `PtMgr` type exported to the rest of the
code, and the background `PtReactor` that actually does the spawning;
this design ensures that only one attempt to spawn a PT is active at a
time, and will prove useful later for implementing e.g. timeouts.
A few changes were necessary to the rest of the code in order to make
this all work out. Namely:
- `TransportRegistry`'s API didn't make any sense for two reasons:
- It wasn't feasible for implementors to implement `ChannelFactory`,
since that'd require constructing a `ChanBuilder` (which requires a
bootstrap reporting event sender).
- Treating the PT manager as a registry is over-general; it's only
necessary for it to spawn pluggable transports, so saddling it with
other concerns didn't make any sense.
- (It's possible to get extensibility for arbitrary user customization
by just letting the user swap in a new `ChannelFactory`, anyway.)
- Therefore, the `PtMgr` implements the new `AbstractPtMgr` trait, which
is far more narrowly focused; this only exists to solve a dependency
loop, and is documented as such.
- This provides a `TransportHelper` instead of a `ChannelFactory`.
This struct is going to be the principal "dictionary-style" serde
representation for a bridge, and the builder, making this all in
keeping with our usual approach.
In this commit:
* Introduce the struct (defining the serialisation)
* Provide the setters (defining the Rust API)
* Add success test cases (not all of the data in which is used yet)
We previously had a trace message on _every_ change. That's fine,
but we also want to log more important changes where the user
can see them. Namely:
* If we go from any other status to Reachable, we want to tell
the user. (We don't want to spam them if it was already
reachable.)
* If we go from Untried or Reachable to Unreachable, we want to
tell the user. (We don't tell them about changes from Retriable
to Unreachable, since that just means that a retry attempt
was not successful.)
Closes#627.
This brings the draft configuration mechanisms in tor-ptmgr in line with
the config in other crates, using builders. It also plumbs the config
type through into the main `arti-client` config, and adds some example
lines to `arti-example-config.toml`.
This introduces the new API functions to Store.
But currently they are all no-ops.
So all this machinery doesn't actually do anything.
Also, it changes the API to the mockable downloader, to allow it to
support if-modified-since. So this isn't used either. But it is more
convenient to do this all at once in BridgeDescManager, since care
needs to be taken about the intraction between if-modified-since and
the persistent cache.
This removes the last cargo audit override (for the unmaintained
ansi_term).
Don't mark options as required when they have default values:
see <https://github.com/clap-rs/clap/pull/3793>.
The new `ipc` module inside `tor-ptmgr` implements the Pluggable
Transport Specification version 1 (`pt-spec.txt`,
https://gitlab.torproject.org/tpo/core/torspec/-/blob/main/pt-spec.txt).
This enables module users to spawn pluggable transport binaries inside a
child process asynchronously, and receive structured information about
how to connect to the transports provided by said binaries.
Internally, this is structured as a pure set of serialisers and
deserialisers for the protocol in the specification (in the form of
environment variables, and the PT's stdout), a wrapper to run the PT
binary and enable accessing its output asynchronously, and a user-facing
wrapper that handles ensuring all the requested transports launched
properly.
The included `run-pt` example is an exceedingly minimal wrapper program
that was useful in testing. More tests can and should be added in a
further MR.
closes arti#394; part of arti#69
The explicit list of variant names, that needs to be kept in sync, and
is a test failure semver break hazard, is now gone.
All the necessary code is now generated automatically, and cannot be
wrong.
I want this because I find myself wanting to add a second
implementation of FlagEvent, for another type.
The most important part of this commit is to make sure that each
`FirstHopId` includes the `GuardSetSelector` from which the guard
was selected. Doing this lets us be certain that when we report
that a guard has succeeded or failed, we're reporting it in the
right context.
Additionally, this commit uses strum to make an iterator over the
samples, so that we can make sure that our "for each sample" code is
robust against future changes, and we don't miss the bridge sample.
This code is _not_ conditional, since we want to support running
with a proxy even if we don't support pluggable transports.
We may eventually want to refactor this into a new create.
Also, add a few tests for this and the other accessors.
We'll need this accessor to find whether we have any channels to
_any_ of the identities that we're trying to connect to.
Also add a BridgeRelayWithDesc type (name tbd) to guarantee that
a bridge relay really does have a known descriptor before you
try to build a circuit with it.
Every element in the set has up to N keys, each of which may have differnt
types. No value for any key may correspond to more than one element in
the set.
These properties can be provided, via a macro, for values of N between 1
and $BIG_ENOUGH.
We'll use this to implement a type that holds HasRelayIds.
(Since the APIs for the `Schedule::sleep*` functions changed, this
is a breaking change in tor-rtcompat. Therefore, the Runtime trait
in tor-rtcompat is now a different trait. Therefore, anything that
uses the Runtime trait in its APIs has also broken.)
This fixes an busy-loop.
When the last `TaskHandle` on a `TaskSchedule` is dropped, the
schedule is permanently canceled: whatever operation it was
scheduling should no longer be performed. But our code was broken:
the `sleep()` and `sleep_until_wallclock()` functions don't verify
whether the handles are dropped or not.
This breakage caused an CPU-eating busy-loop in
`sleep_until_wallclock`.
With this patch, we now return a `Result<(), SleepError>` from these
functions.
Fixes#572.
Because we want to work more on ensuring that our semver stability
story is solid, we are _not_ bumping arti-client to 1.0.0 right now.
Here are the bumps we _are_ doing. Crates with "minor" bumps have
had API breaks; crates with "patch" bumps have had new APIs added.
Note that `tor-congestion` is not bumped here: it's a new crate, and
hasn't been published before.
```
tor-basic-utils minor
fs-mistrust minor
tor-config minor
tor-rtcompat minor
tor-rtmock minor
tor-llcrypto patch
tor-bytes patch
tor-linkspec minor
tor-cell minor
tor-proto minor
tor-netdoc patch
tor-netdir minor
tor-persist patch
tor-chanmgr minor
tor-guardmgr minor
tor-circmgr minor
tor-dirmgr minor
arti-client minor
arti-hyper minor
arti major
arti-bench minor
arti-testing minor
```
Since our last round of releases, these crates have had either
trivial changes, or changes that did not affect their APIs.
Therefore we are bumping their versions, but not changing which
versions of them other crates depend on.
This commit largely follows the example for resolve_alternative_specs.
The difference is that there are two fields, so we use a macro to
avoid recapitulating the field names.
This is more standard. It also provides the ::build() method.
This isn't a config type, and build failures ought not to happen,
so we use Bug for the error.
This is a compile-time feature with an associated configuration
flag, both enabled by default.
When it's turned on, hardening prevents the arti process from
dumping core or being attached to by low-privileged processes.
(This is a defense-in-depth measure, not an absolute way to prevent
attacks. For more information, see
[`secmem_proc`](https://docs.rs/secmem-proc/0.1.1/secmem_proc/).)
Closes#364.
The remaining unconditionally public APIs are those related to our
configuration objects, and the main_main() API.
The rationale for making main_main() public is to have an actual
entry point.
The rationale for making the config APIs public is:
1. We really do intend for others to be able to read our
configuration files using this API.
2. The structure of our configuration files is already part of our
interface.
Closes#530.
This commit implements the round-trip-time estimation algorithm from Tor
proposal 324, validating the implementation against the test vectors
found in C tor. (Note that at the time of writing, the new test vectors
may not be committed to C tor yet, but they will be soon.)
This also adds the necessary consensus parameters to `NetParameters`.
Some of them have been renamed in order to (hopefully) make them more
understandable.
This had to become a new internal function, since at the point that
the handshake needs this code, it does not yet have a Channel to use.
This change made the error messages in the handshake code more
informative: and now they require a regex to check. Later, we might
want to defer formatting these strings, but I don't think we need
to do it now.
Doing this will make sure that we fix a correctness issue in netdir that
will be caused if we add more IDs.
(Also add RelayIdType::COUNT in tor-linkspec.)
The formats used here are backward-compatible with those used by C
tor and those used elsewhere in our code. We need a way to encode
_both_ current kinds of identities as a string that tells you what
kind of ID they are. Traditionally we have used hexadecimal,
sometimes with a $, for RSA ids, and we have used base64 for Ed25519
IDs.
We also introduce a new forward-compatible format for new identity
keys in the future. (The new format is the key identity type, a
colon, and the id encoded as base64.) We will use this new format
_only_ when we need to encode identities in a way where it would be
otherwise unclear what kind of key we are dealing with.
I wonder if these types are correct. I think it makes sense to have
a Ref type like this, rather than just using `&RelayId`, but it
doesn't seems that I can make `RelayId` and `RelayIdRef` implement
Borrow and ToOwned for one another, so maybe I've messed up.
Now we have bus>1 ownership of the crate name `shellexpand`. I have
made a release, and retired `shellexpand-fork`.
The new shellexpand release switches to a (quite similarly) unforked
version of `dirs`.
This Writer is a simple wrapper around `Vec<u8>` that makes sure
that its contents are cleared whenever they are dropped _or
reallocated_.
The reallocation is the important part here: without that, we risk
not zeroizing the first allocation of the buffer.
Using `zeroize` here tells these crates that they should make
various structures zeroize-on-drop.
(This is not yet implemented in `aes` 0.8.1, but support has been
merged in the repository for `aes`, so it should go out in the next
release.)
No corresponding feature flag is needed to enable zeroize-on-drop
for `rsa` and `*25519-dalek` private keys.
This allows us to give better errors in the case where bootstrapping
succeeds at first, but fails thereafter for long enough to make our
directory expire.
We need to replace the AtomicBool for dormant mode with something that
can wake up tasks. postage::watch is the right shape.
But we want to be able to update it but suppress no-op updates.
(There is going to be a call site where no-op updates can occur.)
In the absence of a suitable upstream method as requested here
https://github.com/austinjones/postage-rs/issues/56
we introduce this facility via an extension trait.