Merge branch 'readmes' into 'main'

Abolish maint/readme and use doc include

Closes #603

See merge request tpo/core/arti!768
This commit is contained in:
Nick Mathewson 2022-10-12 15:16:18 +00:00
commit b4cc98b21b
42 changed files with 61 additions and 2109 deletions

View File

@ -53,7 +53,7 @@ This state gets persisted to the locations specified in the
(This method requires you to initialize the client in an `async fn`.
Consider using the builder method, below, if that doesn't work for you.)
```rust
```rust,ignore
// The client configuration describes how to connect to the Tor network,
// and what directories to use for storing persistent state.
let config = TorClientConfig::default();
@ -74,7 +74,7 @@ bootstrap (or having to use an `await`). This can be done by making a
The returned client can be made to bootstrap when it is first used (the
default), or not; see [`BootstrapBehavior`] for more details.
```rust
```rust,ignore
// Specifying `BootstrapBehavior::OnDemand` means the client will automatically
// bootstrap when it is used. `Manual` exists if you'd rather have full control.
let tor_client = TorClient::builder()
@ -93,7 +93,7 @@ those traits if the `tokio` crate feature is enabled.
### Example: making connections over Tor
```rust
```rust,ignore
#
// Initiate a connection over Tor to example.com, port 80.
let mut stream = tor_client.connect(("example.com", 80)).await?;

View File

@ -1,242 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! High-level functionality for accessing the Tor network as a client.
//!
//! # Overview
//!
//! The `arti-client` crate aims to provide a safe, easy-to-use API for
//! applications that want to use the Tor network to anonymize their traffic.
//!
//! This crate is part of [Arti](https://gitlab.torproject.org/tpo/core/arti/),
//! a project to implement [Tor](https://www.torproject.org/) in Rust. It is the
//! highest-level library crate in Arti, and the one that nearly all client-only
//! programs should use. Most of its functionality is provided by lower-level
//! crates in Arti.
//!
//! ## Shape of the API, and relationship to other crates
//!
//! The API here is great if you are building an application in async Rust
//! and want your Tor connections as async streams (`AsyncRead`/`AsyncWrite`).
//! If you are wanting to make HTTP requests,
//! look at [arti_hyper](https://tpo.pages.torproject.net/core/doc/rust/arti_hyper/index.html)).
//!
//! If you are trying to glue Arti to some other programming language,
//! right now your best bet is probably to spawn the
//! [`arti` CLI](https://tpo.pages.torproject.net/core/doc/rust/arti/index.html)
//! SOCKS proxy,
//! as a subprocess.
//! We don't yet offer an API that would be nice to expose via FFI;
//! we intend to add this in the future.
//!
//! ## ⚠ Warnings ⚠
//!
//! Also note that the APIs for this crate are not all yet completely stable.
//! We'll try not to break things without good reason, and we'll follow semantic
//! versioning when we do, but please expect a certain amount of breakage
//! between now and us declaring `arti-client` 1.x.
//!
//! The APIs exposed by lower-level crates in Arti are _even more unstable_;
//! they will break more often than those from `arti-client`, for less reason.
//!
//! # Using `arti-client`
//!
//! The main entry point for this crate is the [`TorClient`], an object that
//! lets you make connections over the Tor network.
//!
//! ## Connecting to Tor
//!
//! Calling [`TorClient::create_bootstrapped`] establishes a connection to the
//! Tor network, pulling in necessary state about network consensus as required.
//! This state gets persisted to the locations specified in the
//! [`TorClientConfig`].
//!
//! (This method requires you to initialize the client in an `async fn`.
//! Consider using the builder method, below, if that doesn't work for you.)
//!
//! ```no_run
//! # use anyhow::Result;
//! # use arti_client::{TorClient, TorClientConfig};
//! # use tokio_crate as tokio;
//! # #[tokio::main]
//! # async fn main() -> Result<()> {
//! // The client configuration describes how to connect to the Tor network,
//! // and what directories to use for storing persistent state.
//! let config = TorClientConfig::default();
//!
//! // Start the Arti client, and let it bootstrap a connection to the Tor network.
//! // (This takes a while to gather the necessary directory information.
//! // It uses cached information when possible.)
//! let tor_client = TorClient::create_bootstrapped(config).await?;
//! # Ok(())
//! # }
//! ```
//!
//! ## Creating a client and connecting later
//!
//! You might wish to create a Tor client immediately, without waiting for it to
//! bootstrap (or having to use an `await`). This can be done by making a
//! [`TorClientBuilder`] with [`TorClient::builder`], and calling
//! [`TorClientBuilder::create_unbootstrapped`].
//!
//! The returned client can be made to bootstrap when it is first used (the
//! default), or not; see [`BootstrapBehavior`] for more details.
//!
//! ```no_run
//! # use anyhow::Result;
//! # use arti_client::{TorClient, TorClientConfig};
//! # use tokio_crate as tokio;
//! # use arti_client::BootstrapBehavior;
//! # #[tokio::main]
//! # async fn main() -> Result<()> {
//! // Specifying `BootstrapBehavior::OnDemand` means the client will automatically
//! // bootstrap when it is used. `Manual` exists if you'd rather have full control.
//! let tor_client = TorClient::builder()
//! .bootstrap_behavior(BootstrapBehavior::OnDemand)
//! .create_unbootstrapped()?;
//! # Ok(())
//! # }
//! ```
//!
//! ## Using the client
//!
//! A client can then be used to make connections over Tor with
//! [`TorClient::connect`], which accepts anything implementing [`IntoTorAddr`].
//! This returns a [`DataStream`], an anonymized TCP stream type that implements
//! [`AsyncRead`](futures::io::AsyncRead) and
//! [`AsyncWrite`](futures::io::AsyncWrite), as well as the Tokio versions of
//! those traits if the `tokio` crate feature is enabled.
//!
//! ## Example: making connections over Tor
//!
//! ```no_run
//! # use anyhow::Result;
//! # use arti_client::{TorClient, TorClientConfig};
//! # use tokio_crate as tokio;
//! # #[tokio::main]
//! # async fn main() -> Result<()> {
//! # let config = TorClientConfig::default();
//! # let tor_client = TorClient::create_bootstrapped(config).await?;
//! #
//! // Initiate a connection over Tor to example.com, port 80.
//! let mut stream = tor_client.connect(("example.com", 80)).await?;
//!
//! use futures::io::{AsyncReadExt, AsyncWriteExt};
//!
//! // Write out an HTTP request.
//! stream
//! .write_all(b"GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n")
//! .await?;
//!
//! // IMPORTANT: Make sure the request was written.
//! // Arti buffers data, so flushing the buffer is usually required.
//! stream.flush().await?;
//!
//! // Read and print the result.
//! let mut buf = Vec::new();
//! stream.read_to_end(&mut buf).await?;
//!
//! println!("{}", String::from_utf8_lossy(&buf));
//! #
//! # Ok(())
//! # }
//! ```
//!
//! ## More advanced usage
//!
//! This version of Arti includes basic support for "stream isolation": the
//! ability to ensure that different TCP connections ('streams') go over
//! different Tor circuits (and thus different exit nodes, making them originate
//! from different IP addresses).
//!
//! This is useful to avoid deanonymizing users by correlation: for example, you
//! might want a Tor connection to your bank and a Tor connection to an online
//! forum to use different circuits, to avoid the possibility of the two
//! identities being linked by having the same source IP.
//!
//! Streams can be isolated in two ways:
//!
//! - by calling [`TorClient::isolated_client`], which returns a new
//! [`TorClient`] whose streams will use a different circuit
//! - by generating [`IsolationToken`]s, and passing them in via [`StreamPrefs`]
//! to [`TorClient::connect`].
//!
//! # Multiple runtime support
//!
//! Arti uses the [`tor_rtcompat`] crate to support multiple asynchronous
//! runtimes; currently, both [Tokio](https://tokio.rs) and
//! [async-std](https://async.rs) are supported.
//!
//! The backend Arti uses for TCP connections ([`tor_rtcompat::TcpProvider`])
//! and for creating TLS sessions ([`tor_rtcompat::TlsProvider`]) is also
//! configurable using this crate. This can be used to embed Arti in custom
//! environments where you want lots of control over how it uses the network.
//!
//! [**View the `tor_rtcompat` crate documentation**](tor_rtcompat) for more
//! about these features.
//!
//! # Feature flags
//!
//! ## Additive features
//!
//! * `tokio` (default) -- build with [Tokio](https://tokio.rs/) support
//! * `native-tls` (default) -- build with the
//! [native-tls](https://github.com/sfackler/rust-native-tls) crate for TLS
//! support
//! * `async-std` -- build with [async-std](https://async.rs/) support
//!
//! * `full` -- Build with all features above, along with all stable additive
//! features from other arti crates. (This does not include experimental
//! features. It also does not include features that select a particular
//! implementation to the exclusion of another, or those that set a build
//! flag.)
//!
//! * `rustls` -- build with the [rustls](https://github.com/rustls/rustls)
//! crate for TLS support. This is not included in `full`, since it uses the
//! `ring` crate, which uses the old (3BSD/SSLEay) OpenSSL license, which may
//! introduce licensing compatibility issues.
//!
//! Note that flags `tokio`, `native-tls`, `async-std`, `rustls` and `static`
//! will enable the flags of the same name on the [`tor_rtcompat`] crate.
//!
//! ## Build-flag related features
//!
//! * `static` -- link with static versions of Arti's system dependencies, like
//! SQLite and OpenSSL (⚠ Warning ⚠: this feature will include a dependency on
//! native-tls, even if you weren't planning to use native-tls. If you only
//! want to build with a static sqlite library, enable the `static-sqlite`
//! feature. We'll look for better solutions here in the future.)
//! * `static-sqlite` -- link with a static version of sqlite.
//! * `static-native-tls` -- link with a static version of `native-tls`. Enables
//! `native-tls`.
//!
//! ## Cryptographic acceleration features
//!
//! Libraries should not enable these by default, since they replace one
//! implementation with another.
//!
//! * `accel-sha1-asm` -- Accelerate cryptography by using an assembly
//! implementation of SHA1, if one is available.
//! * `accel-openssl` -- Accelerate cryptography by using openssl as a backend.
//!
//! ## Experimental and unstable features
//!
//! Note that the APIs enabled by these features are NOT covered by semantic
//! versioning[^1] guarantees: we might break them or remove them between patch
//! versions.
//!
//! * `bridge-client` -- Build with (as yet unimplemented) support for bridges
//! * `pt-client` -- Build with (as yet unimplemented) support for pluggable transports
//! * `experimental-api` -- build with experimental, unstable API support.
//! * `error_detail` -- expose the `arti_client::Error` inner error type.
//! * `dirfilter` -- expose the `DirFilter` API, which lets you modify a network
//! directory before it is used.
//!
//! * `experimental` -- Build with all experimental features above, along with
//! all experimental features from other arti crates.
//!
//! [^1]: Remember, semantic versioning is what makes various `cargo` features
//! work reliably. To be explicit: if you want `cargo update` to _only_ make safe
//! changes, then you cannot enable these features.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,13 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `arti-config`: Removed crate. (Tools for configuration management in Arti)
//!
//! This crate was part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//!
//! The project continues, but this particular crate is now superseded.
//! This empty crate is published as a tombstone.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,14 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! High-level layer for making http(s) requests the Tor network as a client.
//!
//! This can be used by applications which embed Arti,
//! and could also be used as an example of how to build on top of [`arti_client`].
//!
//! There is an example program [`hyper.rs`] which uses `arti-hyper`
//! to connect to Tor and make a single HTTP\[S] request.
//!
//! [`hyper.rs`]: <https://gitlab.torproject.org/tpo/core/arti/-/blob/main/crates/arti-hyper/examples/hyper.rs>
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -63,7 +63,7 @@ To do so, we will launch arti independently from Tor Browser. Build arti with
`cargo build --release`. After that launch it with some basic
configuration parameters:
```
```text
$ ./target/release/arti proxy -l debug -p 9150
```
@ -72,13 +72,13 @@ Tor Browser and instruct it to use that SOCKS port.
#### Linux
```
```text
$ TOR_SKIP_LAUNCH=1 TOR_SOCKS_PORT=9150 TOR_SKIP_CONTROLPORTTEST=1 ./start-tor-browser.desktop
```
#### OS X
```
```text
$ TOR_SKIP_LAUNCH=1 TOR_SOCKS_PORT=9150 TOR_SKIP_CONTROLPORTTEST=1 /path/to/Tor\ Browser/Contents/MacOS/firefox
```
@ -86,13 +86,13 @@ $ TOR_SKIP_LAUNCH=1 TOR_SOCKS_PORT=9150 TOR_SKIP_CONTROLPORTTEST=1 /path/to/Tor\
Create a shortcut with the `Target` set to:
```
```text
C:\Windows\System32\cmd.exe /c "SET TOR_SKIP_LAUNCH=1&& SET TOR_SOCKS_PORT=9150&& TOR_SKIP_CONTROLPORTTEST=1&& START /D ^"C:\path\to\Tor Browser\Browser^" firefox.exe"
```
and `Start in` set to:
```
```text
"C:\path\to\Tor Browser\Browser"
```

View File

@ -1,191 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! A minimal command line program for connecting to the Tor network
//!
//! (If you want a more general Tor client library interface, use
//! [`arti_client`].)
//!
//! This crate is the primary command-line interface for
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to implement
//! [Tor](https://www.torproject.org/) in Rust.
//!
//! Currently Arti can can run as a simple SOCKS proxy over the Tor network.
//! It will listen on port 9150 by default,
//! but you can override this in the configuration.
//! You can direct programs to connect via that SOCKS port,
//! and their connections will be anonymized via Tor.
//! Note: you might not want to run a conventional web browser this way.
//! Browsers leak much private information.
//! To browse the web anonymously,
//! we recommend [using Tor Browser](#using-arti-with-tor-browser).
//!
//! Arti is still advancing rapidly; we are adding features and eventually
//! we hope it will be able to replace C Tor.
//!
//! # Command-line interface
//!
//! (This is not stable; future versions will break this.)
//!
//! `arti` uses the [`clap`](https://docs.rs/clap/) crate for command-line
//! argument parsing; run `arti help` to get it to print its documentation.
//!
//! The only currently implemented subcommand is `arti proxy`; try `arti help
//! proxy` for a list of options you can pass to it.
//!
//! # Configuration
//!
//! By default, `arti` looks for its configuration files in a platform-dependent
//! location.
//!
//! | OS | Configuration File |
//! |---------|----------------------------------------------------|
//! | Unix | `~/.config/arti/arti.toml` |
//! | macOS | `~/Library/Application Support/arti/arti.toml` |
//! | Windows | `\Users\<USERNAME>\AppData\Roaming\arti\arti.toml` |
//!
//! The configuration file is TOML.
//! For an example see `arti-example-config.toml`
//! (a copy of which is in the source tree,
//! and also
//! [in the Arti repository](https://gitlab.torproject.org/tpo/core/arti/-/blob/main/crates/arti/src/arti-example-config.toml)).
//! That example config file documents the configuration options.
//!
//! More detailed information about for the individual fields is available in the documentation
//! for the Rust APIs [`ApplicationConfigBuilder`] and
//! [`TorClientConfigBuilder`](arti_client::config::TorClientConfigBuilder).
//!
//! # Using Arti with Tor Browser
//!
//! It is possible to hook up Arti with
//! [Tor Browser](https://www.torproject.org/download/).
//!
//! To do so, we will launch arti independently from Tor Browser. Build arti with
//! `cargo build --release`. After that launch it with some basic
//! configuration parameters:
//!
//! ```text
//! $ ./target/release/arti proxy -l debug -p 9150
//! ```
//!
//! This will ensure that arti sets its SOCKS port on 9150. Now we need to launch
//! Tor Browser and instruct it to use that SOCKS port.
//!
//! ### Linux
//!
//! ```text
//! $ TOR_SKIP_LAUNCH=1 TOR_SOCKS_PORT=9150 TOR_SKIP_CONTROLPORTTEST=1 ./start-tor-browser.desktop
//! ```
//!
//! ### OS X
//!
//! ```text
//! $ TOR_SKIP_LAUNCH=1 TOR_SOCKS_PORT=9150 TOR_SKIP_CONTROLPORTTEST=1 /path/to/Tor\ Browser/Contents/MacOS/firefox
//! ```
//!
//! ### Windows
//!
//! Create a shortcut with the `Target` set to:
//!
//! ```text
//! C:\Windows\System32\cmd.exe /c "SET TOR_SKIP_LAUNCH=1&& SET TOR_SOCKS_PORT=9150&& TOR_SKIP_CONTROLPORTTEST=1&& START /D ^"C:\path\to\Tor Browser\Browser^" firefox.exe"
//! ```
//!
//! and `Start in` set to:
//!
//! ```text
//! "C:\path\to\Tor Browser\Browser"
//! ```
//!
//! (You may need to adjust the actual path to wherever you have put your Tor
//! Browser.)
//!
//! The resulting Tor Browser should be using arti. Note that onion services
//! and bridges won't work (Arti doesn't support them yet), and neither will
//! any feature depending on Tor's control-port protocol. Features not depending
//! on the control-port such as the "New circuit for this site" button should
//! work.
//!
//! # Compile-time features
//!
//! ## Additive features
//!
//! * `tokio` (default): Use the tokio runtime library as our backend.
//! * `async-std`: Use the async-std runtime library as our backend. This
//! feature has no effect unless building with `--no-default-features` to
//! disable tokio.
//! * `native-tls` -- Build with support for the `native_tls` TLS backend.
//! (default)
//! * `journald` -- Build with support for logging to the `journald` logging
//! backend (available as part of systemd.)
//! * `dns-proxy` (default) -- Build with support for proxying certain simple
//! DNS queries over the Tor network.
//! * `harden` (default) -- Build with support for hardening the Arti process by
//! disabling debugger attachment and other local memory-inspection vectors.
//!
//! * `full` -- Build with all features above, along with all stable additive
//! features from other arti crates. (This does not include experimental
//! features. It also does not include features that select a particular
//! implementation to the exclusion of another, or those that set a build
//! flag.)
//!
//! * `rustls` -- build with the [rustls](https://github.com/rustls/rustls)
//! TLS backend. This is not included in `full`, since it uses the
//! `ring` crate, which uses the old (3BSD/SSLEay) OpenSSL license, which may
//! introduce licensing compatibility issues.
//!
//! ## Build-flag related features
//!
//! * `static` -- Link with static versions of your system dependencies,
//! including sqlite and/or openssl. (⚠ Warning ⚠: this feature will include
//! a dependency on native-tls, even if you weren't planning to use
//! native-tls. If you only want to build with a static sqlite library,
//! enable the `static-sqlite` feature. We'll look for better solutions here
//! in the future.)
//! * `static-sqlite` -- Link with a static version of sqlite.
//! * `static-native-tls` -- Link with a static version of `native-tls`. Enables
//! `native-tls`.
//!
//! ## Cryptographic acceleration features
//!
//! Libraries should not enable these by default, since they replace one
//! implementation with another.
//!
//! * `accel-sha1-asm` -- Accelerate cryptography by using an assembly
//! implementation of SHA1, if one is available.
//! * `accel-openssl` -- Accelerate cryptography by using openssl as a backend.
//!
//! ## Experimental features
//!
//! Note that the APIs enabled by these features are NOT covered by semantic
//! versioning[^1] guarantees: we might break them or remove them between patch
//! versions.
//!
//! * `bridge-client` -- Build with (as yet unimplemented) support for bridges
//! * `pt-client` -- Build with (as yet unimplemented) support for pluggable transports
//! * `experimental-api` -- build with experimental, unstable API support.
//! (Right now, most APIs in the `arti` crate are experimental, since this
//! crate was originally written to run as a binary only.)
//! * `experimental` -- Build with all experimental features above, along with
//! all experimental features from other arti crates.
//!
//! [^1]: Remember, semantic versioning is what makes various `cargo` features
//! work reliably. To be explicit, if you want `cargo update` to _only_ make
//! correct changes, then you cannot enable these features.
//!
//! # Limitations
//!
//! There are many missing features. Among them: there's no onion service
//! support yet. There's no anti-censorship support. You can't be a relay.
//! There isn't any kind of proxy besides SOCKS.
//!
//! See the [repository README
//! file](https://gitlab.torproject.org/tpo/core/arti/-/blob/main/README.md) for
//! a more complete list of missing features.
//!
//! # Library for building command-line client
//!
//! This library crate contains code useful for making a command line program
//! similar to `arti`. The API should not be considered stable.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,43 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `caret`: Integers with some named values.
//!
//! # Crikey! Another Rust Enum Tool?
//!
//! Suppose you have an integer type with some named values. For
//! example, you might be implementing a protocol where "command" can
//! be any 8-bit value, but where only a small number of commands are
//! recognized.
//!
//! In that case, you can use the [`caret_int`] macro to define a
//! wrapper around `u8` so named values are displayed with their
//! preferred format, but you can still represent all the other values
//! of the field:
//!
//! ```
//! use caret::caret_int;
//! caret_int!{
//! struct Command(u8) {
//! Get = 0,
//! Put = 1,
//! Swap = 2,
//! }
//! }
//!
//! let c1: Command = 2.into();
//! let c2: Command = 100.into();
//!
//! assert_eq!(c1.to_string().as_str(), "Swap");
//! assert_eq!(c2.to_string().as_str(), "100");
//!
//! assert_eq!(c1, Command::Swap);
//! ```
//!
//! This crate is developed as part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//! Many other crates in Arti depend on it, but it should be of general
//! use.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -111,7 +111,8 @@ match Mistrust::new().make_directory("/home/itchy/.local/hat-swap") {
You can adjust the [`Mistrust`] object to change what it permits:
```rust
```rust,no_run
# fn main() -> Result<(), fs_mistrust::Error> {
use fs_mistrust::Mistrust;
let my_mistrust = Mistrust::builder()
@ -121,6 +122,8 @@ let my_mistrust = Mistrust::builder()
// available on Unix-like platforms).
// .trust_group(413)
.build()?;
# Ok(())
# }
```
See [`Mistrust`] for more options.
@ -132,7 +135,8 @@ For more fine-grained control over a specific check, you can use the
configure for several requests, the changes in [`Verifier`] generally make
sense only for one request at a time.
```rust
```rust,no_run
# fn main() -> Result<(), fs_mistrust::Error> {
use fs_mistrust::Mistrust;
let mistrust = Mistrust::new();
@ -153,6 +157,8 @@ mistrust
.check_content()
.all_errors()
.make_directory("/home/trace/private_keys/");
# Ok(())
# }
```
See [`Verifier`] for more options.
@ -163,7 +169,8 @@ You can use the [`CheckedDir`] API to ensure not only that a directory is
private, but that all of your accesses to its contents continue to verify
and enforce _their_ permissions.
```rust
```rust,no_run
# fn main() -> Result<(), fs_mistrust::Error> {
use fs_mistrust::{Mistrust, CheckedDir};
use std::fs::{File, OpenOptions};
let dir = Mistrust::new()
@ -177,6 +184,8 @@ dir.make_directory("timelines")?;
let file = dir.open("timelines/vault-destroyed.md",
OpenOptions::new().write(true).create(true))?;
// (... use file...)
# Ok(())
# }
```
### Limitations

View File

@ -1,244 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! # `fs-mistrust`: check whether file permissions are private.
//!
//! This crate provides a set of functionality to check the permissions on files
//! and directories to ensure that they are effectively private—that is, that
//! they are only readable or writable by trusted[^1] users.
//!
//! This kind of check can protect your users' data against misconfigurations,
//! such as cases where they've accidentally made their home directory
//! world-writable, or where they're using a symlink stored in a directory owned
//! by another user.
//!
//! The checks in this crate try to guarantee that, after a path has been shown
//! to be private, no action by a _non-trusted user_ can make that path private.
//! It's still possible for a _trusted user_ to change a path after it has been
//! checked. Because of that, you may want to use other mechanisms if you are
//! concerned about time-of-check/time-of-use issues caused by _trusted_ users
//! altering the filesystem.
//!
//! Also see the [Limitations](#limitations) section below.
//!
//! [^1]: we define "trust" here in the computer-security sense of the word: a
//! user is "trusted" if they have the opportunity to break our security
//! guarantees. For example, `root` on a Unix environment is "trusted",
//! whether you actually trust them or not.
//!
//! ## What's so hard about checking permissions?
//!
//! Suppose that we want to know whether a given path can be read or modified by
//! an untrusted user. That's trickier than it sounds:
//!
//! * Even if the permissions on the file itself are correct, we also need to
//! check the permissions on the directory holding it, since they might allow
//! an untrusted user to replace the file, or change its permissions.
//! * Similarly, we need to check the permissions on the parent of _that_
//! directory, since they might let an untrusted user replace the directory or
//! change _its_ permissions. (And so on!)
//! * It can be tricky to define "a trusted user". On Unix systems, we usually
//! say that each user is trusted by themself, and that root (UID 0) is
//! trusted. But it's hard to say which _groups_ are trusted: even if a given
//! group contains only trusted users today, there's no OS-level guarantee
//! that untrusted users won't be added to that group in the future.
//! * Symbolic links add another layer of confusion. If there are any symlinks
//! in the path you're checking, then you need to check permissions on the
//! directory containing the symlink, and then the permissions on the target
//! path, _and all of its ancestors_ too.
//! * Many programs first canonicalize the path being checked, removing all
//! `..`s and symlinks. That's sufficient for telling whether the _final_
//! file can be modified by an untrusted user, but not for whether the _path_
//! can be modified by an untrusted user. If there is a modifiable symlink in
//! the middle of the path, or at any stage of the path resolution, somebody
//! who can modify that symlink can change which file the path points to.
//! * Even if you have checked a directory as being writeable only by a trusted
//! user, that doesn't mean that the objects _in_ that directory are only
//! writeable by trusted users. Those objects might be symlinks to some other
//! (more writeable) place on the file system; or they might be accessible
//! with hard links stored elsewhere on the file system.
//!
//! Different programs try to solve this problem in different ways, often with
//! very little rationale. This crate tries to give a reasonable implementation
//! for file privacy checking and enforcement, along with clear justifications
//! in its source for why it behaves that way.
//!
//!
//! ## What we actually do
//!
//! To make sure that every step in the file resolution process is checked, we
//! emulate that process on our own. We inspect each component in the provided
//! path, to see whether it is modifiable by an untrusted user. If we encounter
//! one or more symlinks, then we resolve every component of the path added by
//! those symlink, until we finally reach the target.
//!
//! In effect, we are emulating `realpath` (or `fs::canonicalize` if you
//! prefer), and looking at the permissions on every part of the filesystem we
//! touch in doing so, to see who has permissions to change our target file or
//! the process that led us to it.
//!
//! For groups, we use the following heuristic: If there is a group with the
//! same name as the current user, and the current user belongs to that group,
//! we assume that group is trusted. Otherwise, we treat all groups as
//! untrusted.
//!
//! ## Examples
//!
//! ### Simple cases
//!
//! Make sure that a directory is only readable or writeable by us (simple
//! case):
//!
//! ```no_run
//! use fs_mistrust::Mistrust;
//! match Mistrust::new().check_directory("/home/itchy/.local/hat-swap") {
//! Ok(()) => println!("directory is good"),
//! Err(e) => println!("problem with our hat-swap directory: {}", e),
//! }
//! ```
//!
//! As above, but create the directory, and its parents if they do not already
//! exist.
//!
//! ```
//! use fs_mistrust::Mistrust;
//! match Mistrust::new().make_directory("/home/itchy/.local/hat-swap") {
//! Ok(()) => println!("directory exists (or was created without trouble"),
//! Err(e) => println!("problem with our hat-swap directory: {}", e),
//! }
//! ```
//!
//! ### Configuring a [`Mistrust`]
//!
//! You can adjust the [`Mistrust`] object to change what it permits:
//!
//! ```no_run
//! # fn example() -> fs_mistrust::Result<()> {
//! use fs_mistrust::Mistrust;
//!
//! let my_mistrust = Mistrust::builder()
//! // Assume that our home directory and its parents are all well-configured.
//! .ignore_prefix("/home/doze/")
//! // Assume that a given group will only contain trusted users (this feature is only
//! // available on Unix-like platforms).
//! // .trust_group(413)
//! .build()?;
//! # Ok(())
//! # }
//! ```
//!
//! See [`Mistrust`] for more options.
//!
//! ### Using [`Verifier`] for more fine-grained checks
//!
//! For more fine-grained control over a specific check, you can use the
//! [`Verifier`] API. Unlike [`Mistrust`], which generally you'll want to
//! configure for several requests, the changes in [`Verifier`] generally make
//! sense only for one request at a time.
//!
//! ```no_run
//! # fn example() -> fs_mistrust::Result<()> {
//! use fs_mistrust::Mistrust;
//! let mistrust = Mistrust::new();
//!
//! // Require that an object is a regular file; allow it to be world-
//! // readable.
//! mistrust
//! .verifier()
//! .permit_readable()
//! .require_file()
//! .check("/home/trace/.path_cfg")?;
//!
//! // Make sure that a directory _and all of its contents_ are private.
//! // Create the directory if it does not exist.
//! // Return an error object containing _all_ of the problems discovered.
//! mistrust
//! .verifier()
//! .require_directory()
//! .check_content()
//! .all_errors()
//! .make_directory("/home/trace/private_keys/");
//! # Ok(())
//! # }
//! ```
//!
//! See [`Verifier`] for more options.
//!
//! ### Using [`CheckedDir`] for safety.
//!
//! You can use the [`CheckedDir`] API to ensure not only that a directory is
//! private, but that all of your accesses to its contents continue to verify
//! and enforce _their_ permissions.
//!
//! ```
//! # fn example() -> anyhow::Result<()> {
//! use fs_mistrust::{Mistrust, CheckedDir};
//! use std::fs::{File, OpenOptions};
//! let dir = Mistrust::new()
//! .verifier()
//! .secure_dir("/Users/clover/riddles")?;
//!
//! // You can use the CheckedDir object to access files and directories.
//! // All of these must be relative paths within the path you used to
//! // build the CheckedDir.
//! dir.make_directory("timelines")?;
//! let file = dir.open("timelines/vault-destroyed.md",
//! OpenOptions::new().write(true).create(true))?;
//! // (... use file...)
//! # Ok(())
//! # }
//! ```
//!
//! ## Limitations
//!
//! As noted above, this crate only checks whether a path can be changed by
//! _non-trusted_ users. After the path has been checked, a _trusted_ user can
//! still change its permissions. (For example, the user could make their home
//! directory world-writable.) This crate does not try to defend against _that
//! kind_ of time-of-check/time-of-use issue.
//!
//! We currently assume a fairly vanilla Unix environment: we'll tolerate other
//! systems, but we don't actually look at the details of any of these:
//! * Windows security (ACLs, SecurityDescriptors, etc)
//! * SELinux capabilities
//! * POSIX (and other) ACLs.
//!
//! We use a somewhat inaccurate heuristic when we're checking the permissions
//! of items _inside_ a target directory (using [`Verifier::check_content`] or
//! [`CheckedDir`]): we continue to forbid untrusted-writeable directories and
//! files, but we still allow readable ones, even if we insisted that the target
//! directory itself was required to to be unreadable. This is too permissive
//! in the case of readable objects with hard links: if there is a hard link to
//! the file somewhere else, then an untrusted user can read it. It is also too
//! restrictive in the case of writeable objects _without_ hard links: if
//! untrusted users have no path to those objects, they can't actually write
//! them.
//!
//! On Windows, we accept all file permissions and owners.
//!
//! We don't check for mount-points and the privacy of filesystem devices
//! themselves. (For example, we don't distinguish between our local
//! administrator and the administrator of a remote filesystem. We also don't
//! distinguish between local filesystems and insecure networked filesystems.)
//!
//! This code has not been audited for correct operation in a setuid
//! environment; there are almost certainly security holes in that case.
//!
//! This is fairly new software, and hasn't been audited yet.
//!
//! All of the above issues are considered "good to fix, if practical".
//!
//! ## Acknowledgements
//!
//! The list of checks performed here was inspired by the lists from OpenSSH's
//! [safe_path], GnuPG's [check_permissions], and Tor's [check_private_dir]. All
//! errors are my own.
//!
//! [safe_path]:
//! https://github.com/openssh/openssh-portable/blob/master/misc.c#L2177
//! [check_permissions]:
//! https://github.com/gpg/gnupg/blob/master/g10/gpg.c#L1551
//! [check_private_dir]:
//! https://gitlab.torproject.org/tpo/core/tor/-/blob/main/src/lib/fs/dir.c#L70
#![doc = include_str!("../README.md")]
// TODO: Stuff to add before this crate is ready....
// - Test the absolute heck out of it.

View File

@ -1,40 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! An error attempt to represent multiple failures.
//!
//! This crate implements [`RetryError`], a type to use when you
//! retry something a few times, and all those attempts can fail differently
//! each time. Instead of returning only a single error, it records
//! _all of the errors received_, in case they are different.
//!
//! This crate is developed as part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//! It's used by higher-level crates that retry
//! operations.
//!
//! ## Example
//!
//! ```rust
//!use retry_error::RetryError;
//!
//!fn some_operation() -> anyhow::Result<bool> {
//! unimplemented!(); // example
//!}
//!
//!fn example() -> Result<(), RetryError<anyhow::Error>> {
//! const N_ATTEMPTS: usize = 10;
//! let mut err = RetryError::in_attempt_to("perform an example operation");
//! for _ in 0..N_ATTEMPTS {
//! match some_operation() {
//! Ok(val) => return Ok(()),
//! Err(e) => err.push(e),
//! }
//! }
//! // All attempts failed; return all the errors.
//! return Err(err);
//!}
//! ```
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -35,6 +35,9 @@ You can disable safe-logging globally (across all threads) or locally
(across a single thread).
```rust
# let debug_mode = true;
# let log_encrypted_data = |_|();
# let big_secret = ();
use safelog::{disable_safe_logging, with_safe_logging_suppressed};
// If we're running in debug mode, turn off safe logging

View File

@ -1,74 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! # `safelog`: Mark data as sensitive for logging purposes.
//!
//! Some information is too sensitive to routinely write to system logs, but
//! must nonetheless sometimes be displayed. This crate provides a way to mark
//! such information, and log it conditionally, but not by default.
//!
//! ## Examples
//!
//! There are two main ways to mark a piece of data as sensitive: by storing it
//! within a [`Sensitive`] object long-term, or by wrapping it in a
//! [`Sensitive`] object right before passing it to a formatter:
//!
//! ```
//! use safelog::{Sensitive, sensitive};
//!
//! // With this declaration, a student's name and gpa will be suppressed by default
//! // when passing the student to Debug.
//! #[derive(Debug)]
//! struct Student {
//! name: Sensitive<String>,
//! grade: u8,
//! homeroom: String,
//! gpa: Sensitive<f32>,
//! }
//!
//! // In this function, a user's IP will not be printed by default.
//! fn record_login(username: &str, ip: &std::net::IpAddr) {
//! println!("Login from {} at {}", username, sensitive(ip));
//! }
//! ```
//!
//! You can disable safe-logging globally (across all threads) or locally
//! (across a single thread).
//!
//! ```
//! use safelog::{disable_safe_logging, with_safe_logging_suppressed};
//! # let debug_mode = false;
//! # fn log_encrypted_data(s: &str) {}
//! # let big_secret = "swordfish";
//!
//! // If we're running in debug mode, turn off safe logging
//! // globally. Safe logging will remain disabled until the
//! // guard object is dropped.
//! let guard = if debug_mode {
//! // This call can fail if safe logging has already been enforced.
//! disable_safe_logging().ok()
//! } else {
//! None
//! };
//!
//! // If we know that it's safe to record sensitive data with a given API,
//! // we can disable safe logging temporarily. This affects only the current thread.
//! with_safe_logging_suppressed(|| log_encrypted_data(big_secret));
//! ```
//!
//! ## An example deployment
//!
//! This crate was originally created for use in the `arti` project, which tries
//! to implements the Tor anonymity protocol in Rust. In `arti`, we want to
//! avoid logging information by default if it could compromise users'
//! anonymity, or create an incentive for attacking users and relays in order to
//! access their logs.
//!
//! In general, Arti treats the following information as [`Sensitive`]:
//! * Client addresses.
//! * The destinations (target addresses) of client requests.
//!
//! Arti does _not_ label all private information as `Sensitive`: when
//! information isn't _ever_ suitable for logging, we omit it entirely.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,15 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `tor-basic-utils`: Utilities (low-level) for Tor
//!
//! Miscellaneous utilities for `tor-*` and `arti-*`.
//!
//! This crate lives at the *bottom* of the Tor crate stack.
//! So it contains only utilities which have no `tor-*` (or `arti-*`) dependencies.
//!
//! There is no particular theme.
//! More substantial sets of functionality with particular themes
//! are to be found in other `tor-*` crates.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,53 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `tor-bytes`: Utilities to decode/encode things into bytes.
//!
//! # Overview
//!
//! The `tor-bytes` crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//! Other crates in Arti use it to build and handle all the byte-encoded
//! objects from the Tor protocol. For textual directory items, see
//! the [`tor-netdoc`] crate.
//!
//! This crate is generally useful for encoding and decoding
//! byte-oriented formats that are not regular enough to qualify for
//! serde, and not complex enough to need a full meta-language. It is
//! probably not suitable for handling anything bigger than a few
//! kilobytes in size.
//!
//! ## Alternatives
//!
//! The Reader/Writer traits in std::io are more appropriate for
//! operations that can fail because of some IO problem. This crate
//! can't handle that: it is for handling things that are already in
//! memory.
//!
//! TODO: Look into using the "bytes" crate more here.
//!
//! TODO: The "untrusted" crate has similar goals to our [`Reader`],
//! but takes more steps to make sure it can never panic. Perhaps we
//! should see if we can learn any tricks from it.
//!
//! TODO: Do we really want to keep `Reader` as a struct and
//! `Writer` as a trait?
//!
//! # Contents and concepts
//!
//! This crate is structured around four key types:
//!
//! * [`Reader`]: A view of a byte slice, from which data can be decoded.
//! * [`Writer`]: Trait to represent a growable buffer of bytes.
//! (Vec<u8> and [`bytes::BytesMut`] implement this.)
//! * [`Writeable`]: Trait for an object that can be encoded onto a [`Writer`]
//! * [`Readable`]: Trait for an object that can be decoded from a [`Reader`].
//!
//! Every object you want to encode or decode should implement
//! [`Writeable`] or [`Readable`] respectively.
//!
//! Once you implement these traits, you can use Reader and Writer to
//! handle your type, and other types that are built around it.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,63 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! Coding and decoding for the cell types that make up Tor's protocol
//!
//! # Overview
//!
//! Tor's primary network protocol is oriented around a set of
//! messages called "Cells". They exist at two primary layers of the
//! protocol: the channel-cell layer, and the relay-cell layer.
//!
//! [Channel cells](chancell::ChanCell) are sent between relays, or
//! between a client and a relay, over a TLS connection. Each of them
//! encodes a single [Channel Message](chancell::msg::ChanMsg).
//! Channel messages can affect the channel itself (such as those used
//! to negotiate and authenticate the channel), but more frequently are
//! used with respect to a given multi-hop circuit.
//!
//! Channel message that refer to a circuit do so with a channel-local
//! identifier called a [Circuit ID](chancell::CircId). These
//! messages include CREATE2 (used to extend a circuit to a first hop)
//! and DESTROY (used to tear down a circuit). But the most
//! frequently used channel message is RELAY, which is used to send a
//! message to a given hop along a circuit.
//!
//! Each RELAY cell is encrypted and decrypted (according to protocols
//! not implemented in this crate) until it reaches its target. When
//! it does, it is decoded into a single [Relay
//! Message](relaycell::msg::RelayMsg). Some of these relay messages
//! are used to manipulate circuits (e.g., by extending the circuit to
//! a new hop); others are used to manipulate anonymous data-streams
//! (by creating them, ending them, or sending data); and still others
//! are used for protocol-specific purposes (like negotiating with an
//! onion service.)
//!
//! For a list of _most_ of the cell types used in Tor, see
//! [tor-spec.txt](https://spec.torproject.org/tor-spec). Other cell
//! types are defined in [rend-spec-v3.txt (for onion
//! services)](https://spec.torproject.org/tor-spec) and
//! [padding-spec.txt (for padding
//! negotiation)](https://spec.torproject.org/padding-spec).
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//!
//! # Futureproofing note
//!
//! There are two pending proposals to remove the one-to-one
//! correspondence between relay cells and relay messages.
//!
//! [Proposal 319](https://gitlab.torproject.org/tpo/core/torspec/-/blob/master/proposals/319-wide-everything.md)
//! would add a "RELAY_FRAGMENT" command that would allow larger relay
//! messages to span multiple RELAY cells.
//!
//! [Proposal 325](https://gitlab.torproject.org/tpo/core/torspec/-/blob/master/proposals/325-packed-relay-cells.md),
//! on the other hand, would allow multiple relay messages to be
//! packed into a single RELAY cell.
//!
//! The distinction between RelayCell and RelayMsg is meant in part
//! to future-proof arti against these proposals if they are adopted.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,56 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! Implementation for Tor certificates
//!
//! # Overview
//!
//! The `tor-cert` crate implements the binary certificate types
//! documented in Tor's cert-spec.txt, which are used when
//! authenticating Tor channels. (Eventually, support for onion service
//! certificate support will get added too.)
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//!
//! There are other types of certificate used by Tor as well, and they
//! are implemented in other places. In particular, see
//! [`tor-netdoc::doc::authcert`] for the certificate types used by
//! authorities in the directory protocol.
//!
//! ## Design notes
//!
//! The `tor-cert` code is in its own separate crate because it is
//! required by several other higher-level crates that do not depend
//! upon each other. For example, [`tor-netdoc`] parses encoded
//! certificates from router descriptors, while [`tor-proto`] uses
//! certificates when authenticating relays.
//!
//! # Examples
//!
//! Parsing, validating, and inspecting a certificate:
//!
//! ```
//! use base64::decode;
//! use tor_cert::*;
//! use tor_checkable::*;
//! // Taken from a random relay on the Tor network.
//! let cert_base64 =
//! "AQQABrntAThPWJ4nFH1L77Ar+emd4GPXZTPUYzIwmR2H6Zod5TvXAQAgBAC+vzqh
//! VFO1SGATubxcrZzrsNr+8hrsdZtyGg/Dde/TqaY1FNbeMqtAPMziWOd6txzShER4
//! qc/haDk5V45Qfk6kjcKw+k7cPwyJeu+UF/azdoqcszHRnUHRXpiPzudPoA4=";
//! // Remove the whitespace, so base64 doesn't choke on it.
//! let cert_base64: String = cert_base64.split_whitespace().collect();
//! // Decode the base64.
//! let cert_bin = base64::decode(cert_base64).unwrap();
//!
//! // Decode the cert and check its signature.
//! let cert = Ed25519Cert::decode(&cert_bin).unwrap()
//! .check_key(None).unwrap()
//! .check_signature().unwrap()
//! .dangerously_assume_timely();
//! let signed_key = cert.subject_key();
//! ```
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,38 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `tor-chanmgr`: Manage a set of channels on the Tor network.
//!
//! # Overview
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//!
//! In Tor, a channel is a connection to a Tor relay. It can be
//! direct via TLS, or indirect via TLS over a pluggable transport.
//! (For now, only direct channels are supported.)
//!
//! Since a channel can be used for more than one circuit, it's
//! important to reuse channels when possible. This crate implements
//! a [`ChanMgr`] type that can be used to create channels on demand,
//! and return existing channels when they already exist.
//! # Compile-time features
//!
//! ## Experimental and unstable features
//!
//! Note that the APIs enabled by these features are NOT covered by
//! semantic versioning[^1] guarantees: we might break them or remove
//! them between patch versions.
//!
//! * `pt-client` -- Build with (as yet unimplemented) APIs to support
//! pluggable transports.
//!
//! * `experimental` -- Build with all experimental features above.
//!
//! [^1]: Remember, semantic versioning is what makes various `cargo`
//! features work reliably. To be explicit: if you want `cargo update`
//! to _only_ make safe changes, then you cannot enable these
//! features.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,48 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! Traits for wrapping up signed and/or time-bound objects
//!
//! # Overview
//!
//! Frequently (for testing reasons or otherwise), we want to ensure
//! that an object can only be used if a signature is valid, or if
//! some timestamp is recent enough.
//!
//! As an example, consider a self-signed certificate. You can parse
//! it cheaply enough (and find its key by doing so), but you probably
//! want to make sure that nobody will use that certificate unless its
//! signature is correct and its timestamps are not expired.
//!
//! With the tor-checkable crate, you can instead return an object
//! that represents the certificate in its unchecked state. The
//! caller can access the certificate, but only after checking the
//! signature and the time.
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//! Many other crates in Arti depend on it, but it should be generally
//! useful outside of Arti.
//!
//! ## Design notes and alternatives
//!
//! The types in this crate provide functions to return the underlying
//! objects without checking them. This is very convenient for testing,
//! though you wouldn't want to do it in production code. To prevent
//! mistakes, these functions all begin with the word `dangerously`.
//!
//! Another approach you might take is to put signature and timeliness
//! checks inside your parsing function. But if you do that, it will
//! get hard to test your code: you will only be able to parse
//! certificates that are valid when the parser is running. And if
//! you want to test parsing a new kind of certificate, you'll need to
//! make sure to put a valid signature on it. (And all of this
//! signature parsing will slow down any attempts to fuzz your
//! parser.)
//!
//! You could have your parser take a flag to tell it whether to check
//! signatures and timeliness, but that could be error prone: if anybody
//! sets the flag wrong, they will skip doing the checks.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,26 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `tor-circmgr`: circuits through the Tor network on demand.
//!
//! # Overview
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//!
//! In Tor, a circuit is an encrypted multi-hop tunnel over multiple
//! relays. This crate's purpose, long-term, is to manage a set of
//! circuits for a client. It should construct circuits in response
//! to a client's needs, and preemptively construct circuits so as to
//! anticipate those needs. If a client request can be satisfied with
//! an existing circuit, it should return that circuit instead of
//! constructing a new one.
//!
//! # Limitations
//!
//! But for now, this `tor-circmgr` code is extremely preliminary; its
//! data structures are all pretty bad, and it's likely that the API
//! is wrong too.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,62 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `tor-config`: Tools for configuration management in Arti
//!
//! # Overview
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//!
//! It provides types for handling configuration values,
//! and general machinery for configuration management.
//!
//! # Configuration in Arti
//!
//! The configuration for the `arti` command line program,
//! and other programs which embed Arti reusing the configuration machinery,
//! works as follows:
//!
//! 1. We use [`tor_config::ConfigurationSources`](ConfigurationSources)
//! to enumerate the various places
//! where configuration information needs to come from,
//! and configure how they are to be read.
//! `arti` uses [`ConfigurationSources::from_cmdline`].
//!
//! 2. [`ConfigurationSources::load`] actually *reads* all of these sources,
//! parses them (eg, as TOML files),
//! and returns a [`config::Config`].
//! This is a tree-structured dynamically typed data structure,
//! mirroring the input configuration structure, largely unvalidated,
//! and containing everything in the input config sources.
//!
//! 3. We call one of the [`tor_config::resolve`](resolve) family.
//! This maps the input configuration data to concrete `ConfigBuilder `s
//! for the configuration consumers within the program.
//! (For `arti`, that's `TorClientConfigBuilder` and `ArtiBuilder`).
//! This mapping is done using the `Deserialize` implementations on the `Builder`s.
//! `resolve` then calls the `build()` method on each of these parts of the configuration
//! which applies defaults and validates the resulting configuration.
//!
//! It is important to call `resolve` *once* for *all* the configuration consumers,
//! so that it sees a unified view of which config settings in the input
//! were unrecognized, and therefore may need to be reported to the user.
//! See the example in the [`load`] module documentation.
//!
//! 4. The resulting configuration objects (eg, `TorClientConfig`, `ArtiConfig`)
//! are provided to the code that must use them (eg, to make a `TorClient`).
//!
//! See the
//! [`tor_config::load` module-level documentation](load).
//! for an example.
//!
//! # ⚠ Stability Warning ⚠
//!
//! The design of this crate, and of the configuration system for
//! Arti, is likely to change significantly before the release of Arti
//! 1.0.0. For more information see ticket [#285].
//!
//! [#285]: https://gitlab.torproject.org/tpo/core/arti/-/issues/285
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,16 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `tor-congestion`: algorithms for congestion control on the Tor network
//!
//! # Overview
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//!
//! This implements some of the algorithms needed to implement congestion control
//! as part of
//! [Tor proposal #324](https://gitlab.torproject.org/tpo/core/torspec/-/blob/main/proposals/324-rtt-congestion-control.txt).
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,22 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `tor-consdiff`: Restricted ed diff and patch formats for Tor.
//!
//! # Overview
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//! Tor uses a restricted version of the "ed-style" diff format to
//! record the difference between a pair of consensus documents, so that
//! clients can download only the changes since the last document they
//! have.
//!
//! This crate provides a function to apply one of these diffs to an older
//! consensus document, to get a newer one.
//!
//! TODO: Eventually, when we add relay support, we will need to generate
//! these diffs as well as consume them.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,30 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `tor-dirclient`: Implements a minimal directory client for Tor.
//!
//! # Overview
//!
//! Tor makes its directory requests as HTTP/1.0 requests tunneled over
//! Tor circuits. For most objects, Tor uses a one-hop tunnel. Tor
//! also uses a few strange and ad-hoc HTTP headers to select
//! particular functionality, such as asking for diffs, compression,
//! or multiple documents.
//!
//! This crate provides an API for downloading Tor directory resources
//! over a Tor circuit.
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//!
//! # Features
//!
//! `xz` -- enable XZ compression. This can be expensive in RAM and CPU,
//! but it saves a lot of bandwidth. (On by default.)
//!
//! `zstd` -- enable ZSTD compression. (On by default.)
//!
//! `routerdesc` -- Add support for downloading router descriptors.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,56 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `tor-dirmgr`: Code to fetch, store, and update Tor directory information.
//!
//! # Overview
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//!
//! In its current design, Tor requires a set of up-to-date
//! authenticated directory documents in order to build multi-hop
//! anonymized circuits through the network.
//!
//! This directory manager crate is responsible for figuring out which
//! directory information we lack, downloading what we're missing, and
//! keeping a cache of it on disk.
//!
//! # Compile-time features
//!
//! `mmap` (default) -- Use memory mapping to reduce the memory load for
//! reading large directory objects from disk.
//!
//! `static` -- Try to link with a static copy of sqlite3.
//!
//! `routerdesc` -- (Incomplete) support for downloading and storing
//! router descriptors.
//!
//! ## Experimental features
//!
//! # Compile-time features
//!
//! ## Experimental and unstable features
//!
//! Note that the APIs enabled by these features are NOT covered by
//! semantic versioning[^1] guarantees: we might break them or remove
//! them between patch versions.
//!
//! * `experimental-api`: Add additional non-stable APIs to our public
//! interfaces.
//!
//! * `dirfilter`: enable an experimental mechanism to modify incoming
//! directory informatoin before it is used.
//!
//! * `bridge-client`: Provide (as yet unimplented) APIs used to fetch
//! and use bridge information.
//!
//! * `experimental`: Enable all the above experimental features.
//!
//! [^1]: Remember, semantic versioning is what makes various `cargo`
//! features work reliably. To be explicit: if you want `cargo update`
//! to _only_ make safe changes, then you cannot enable these
//! features.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,12 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `tor-error` -- Support for error handling in Tor and Arti
//!
//! Primarily, this crate provides the [`ErrorKind`] enum,
//! and associated [`HasKind`] trait.
//!
//! There is also some other miscellany, supporting error handling in
//! crates higher up the dependency stack.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,6 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! Tools for generating a stream of structured events, similar to C tor's `ControlPort`.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,97 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `tor-guardmgr`: guard node selection for Tor network clients.
//!
//! # Overview
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//!
//! "Guard nodes" are mechanism that Tor clients uses to limit the
//! impact of hostile relays. Approximately: each client chooses a
//! small set of relays to use as its "guards". Later, when the
//! client picks its paths through network, rather than choosing a
//! different first hop randomly for every path, it chooses the best
//! "guard" as the first hop.
//!
//! This crate provides [`GuardMgr`], an object that manages a set of
//! guard nodes, and helps the `tor-circmgr` crate know when to use
//! them.
//!
//! Guard nodes are persistent across multiple process invocations.
//!
//! More Arti users won't need to use this crate directly.
//!
//! # Motivation
//!
//! What's the point? By restricting their first hops to a small set,
//! clients increase their odds against traffic-correlation attacks.
//! Since we assume that an adversary who controls both ends of a
//! circuit can correlate its traffic, choosing many circuits with
//! random entry points will eventually cause a client to eventually
//! pick an attacker-controlled circuit, with probability approaching
//! 1 over time. If entry nodes are restricted to a small set,
//! however, then the client has a chance of never picking an
//! attacker-controlled circuit.
//!
//! (The actual argument is a little more complicated here, and it
//! relies on the assumption that, since the attacker knows
//! statistics, exposing _any_ of your traffic is nearly as bad as
//! exposing _all_ of your traffic.)
//!
//! # Complications
//!
//! The real algorithm for selecting and using guards can get more
//! complicated because of a variety of factors.
//!
//! - In reality, we can't just "pick a few guards at random" and use
//! them forever: relays can appear and disappear, relays can go
//! offline and come back online, and so on. What's more, keeping
//! guards for too long can make targeted attacks against those
//! guards more attractive.
//!
//! - Further, we may have particular restrictions on where we can
//! connect. (For example, we might be restricted to ports 80 and
//! 443, but only when we're on a commuter train's wifi network.)
//!
//! - We need to resist attacks from local networks that block all but a
//! small set of guard relays, to force us to choose those.
//!
//! - We need to give good, reliable performance while using the
//! guards that we prefer.
//!
//! These needs complicate our API somewhat. Instead of simply asking
//! the `GuardMgr` for a guard, the circuit-management code needs to
//! be able to tell the `GuardMgr` that a given guard has failed (or
//! succeeded), and that it needs a different guard in the future (or
//! not).
//!
//! Further, the `GuardMgr` code needs to be able to hand out
//! _provisional guards_, in effect saying "You can try building a
//! circuit with this guard, but please don't actually _use_ that
//! circuit unless I tell you it's safe."
//!
//! For details on the exact algorithm, see `guard-spec.txt` (link
//! below) and comments and internal documentation in this crate.
//!
//! # Limitations
//!
//! * Our circuit blocking algorithm is simplified from the one that Tor uses.
//! See comments in `GuardSet::circ_usability_status` for more information.
//! See also [proposal 337](https://gitlab.torproject.org/tpo/core/torspec/-/blob/main/proposals/337-simpler-guard-usability.md).
//!
//! # References
//!
//! Guard nodes were first proposes (as "helper nodes") in "Defending
//! Anonymous Communications Against Passive Logging Attacks" by
//! Matthew Wright, Micah Adler, Brian N. Levine, and Clay Shields in
//! the Proceedings of the 2003 IEEE Symposium on Security and
//! Privacy. (See <https://www.freehaven.net/anonbib/#wright03>)
//!
//! Tor's current guard selection algorithm is described in Tor's
//! [`guard-spec.txt`](https://gitlab.torproject.org/tpo/core/torspec/-/raw/main/guard-spec.txt)
//! document.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,60 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `tor-linkspec`: Descriptions of Tor relays, as used to connect to them.
//!
//! # Overview
//!
//! The `tor-linkspec` crate provides traits and data structures that
//! describe how to connect to Tor relays.
//!
//! When describing the location of a Tor relay on the network, the
//! Tor protocol uses a set of "link specifiers", each of which
//! corresponds to a single aspect of the relay's location or
//! identity—such as its IP address and port, its Ed25519 identity
//! key, its (legacy) RSA identity fingerprint, or so on. This
//! crate's [`LinkSpec`] type encodes these structures.
//!
//! When a client is building a circuit through the Tor network, it
//! needs to know certain information about the relays in that
//! circuit. This crate's [`ChanTarget`] and [`CircTarget`] traits
//! represent objects that describe a relay on the network that a
//! client can use as the first hop, or as any hop, in a circuit.
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust. Several
//! other crates in Arti depend on it. You will probably not need
//! this crate yourself unless you are interacting with the Tor
//! protocol at a fairly low level.
//!
//! `tor-linkspec` is a separate crate so that it can be used by other
//! crates that expose link specifiers and by crates that consume
//! them.
//!
//! ## Future work
//!
//! TODO: Possibly we should rename this crate. "Linkspec" is a
//! pretty esoteric term in the Tor protocols.
//!
//! TODO: Possibly the link specifiers and the `*Target` traits belong in different crates.
//!
//! # Compile-time features
//!
//! ## Experimental and unstable features
//!
//! Note that the APIs enabled by these features are NOT covered by
//! semantic versioning[^1] guarantees: we might break them or remove
//! them between patch versions.
//!
//! * `pt-client` -- Build with enhanced data types to support pluggable
//! transports.
//!
//! * `experimental` -- Build with all experimental features above.
//!
//! [^1]: Remember, semantic versioning is what makes various `cargo`
//! features work reliably. To be explicit: if you want `cargo update`
//! to _only_ make safe changes, then you cannot enable these
//! features.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,79 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `tor-llcrypto`: Low-level cryptographic implementations for Tor.
//!
//! # Overview
//!
//! The `tor-llcrypto` crate wraps lower-level cryptographic primitives that Tor
//! needs, and provides a few smaller pieces of cryptographic functionality that
//! are commonly required to implement Tor correctly.
//!
//! This crate is part of [Arti](https://gitlab.torproject.org/tpo/core/arti/),
//! a project to implement [Tor](https://www.torproject.org/) in Rust. Many
//! other crates in Arti depend on it.
//!
//! You probably wouldn't want to use this crate for implementing non-Tor-based
//! protocols; instead you should probably use the other crates that it depends
//! on if you have a low-level protocol to implement, or a higher-level
//! cryptographic system if you want to add security to something else. It is
//! easy to accidentally put these functions together in ways that are unsafe.
//!
//! ## Why a separate crate?
//!
//! Why do we collect and re-export our cryptography here in `tor-llcrypto`,
//! instead of having the different crates in Arti use underlying cryptographic
//! crates directly?
//!
//! By wrapping our cryptography in this crate, we ensure that we're using the
//! same implementations across our ecosystem, and provide a single place to
//! upgrade and test our cryptography.
//!
//! ## Adding to `tor-llcrypto`
//!
//! Any low-level cryptographic algorithm that is used by at least two other
//! crates in Arti is a candidate for inclusion in `tor-llcrypto`, especially if
//! that algorithm's purpose is not specific to any single piece of the Tor
//! algorithm.
//!
//! Cryptographic _traits_ (like those from RustCrypto) don't have to go in
//! `tor-llcrypto`, since they are interfaces rather than implementations.
//!
//! # Contents
//!
//! Encryption is implemented in [`cipher`]: Currently only AES is exposed or
//! needed.
//!
//! Cryptographic digests are in [`d`]: The Tor protocol uses several digests in
//! different places, and these are all collected here.
//!
//! Public key cryptography (including signatures, encryption, and key
//! agreement) are in [`pk`]. Older parts of the Tor protocol require RSA;
//! newer parts are based on Curve25519 and Ed25519. There is also functionality
//! here for _key manipulation_ for the keys used in these symmetric algorithms.
//!
//! The [`util`] module has some miscellaneous compatibility utilities for
//! manipulating cryptography-related objects and code.
//!
//! # Features
//!
//! ## API features
//!
//! `relay` -- enable cryptography that's only used on relays.
//!
//! `hsv3-client` -- enable cryptography that's only needed when running as a v3
//! onion service client.
//!
//! ## Acceleration features
//!
//! These features should never be enabled by default from libraries, since they
//! are not "strictly additive": they disable one implementation in order to
//! enable another.
//!
//! `with-openssl` -- Use `openssl` as the backend for those cryptographic
//! features it supports.
//!
//! `with-sha1-asm` -- Use an assembly implementation of the sha1 algorithm, if
//! one is enabled.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,31 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! Represents a clients'-eye view of the Tor network.
//!
//! # Overview
//!
//! The `tor-netdir` crate wraps objects from tor-netdoc, and combines
//! them to provide a unified view of the relays on the network.
//! It is responsible for representing a client's knowledge of the
//! network's state and who is on it.
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust. Its purpose
//! is to expose an abstract view of a Tor network and the relays in
//! it, so that higher-level crates don't need to know about the
//! particular documents that describe the network and its properties.
//!
//! There are two intended users for this crate. First, producers
//! like [`tor-dirmgr`] create [`NetDir`] objects fill them with
//! information from the Tor network directory. Later, consumers
//! like [`tor-circmgr`] use [`NetDir`]s to select relays for random
//! paths through the Tor network.
//!
//! # Limitations
//!
//! Only modern consensus methods and microdescriptor consensuses are
//! supported.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,56 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! Parse and represent directory objects used in Tor.
//!
//! # Overview
//!
//! Tor has several "directory objects" that it uses to convey
//! information about relays on the network. They are documented in
//! dir-spec.txt.
//!
//! This crate has common code to parse and validate these documents.
//! Currently, it can handle the metaformat, along with certain parts
//! of the router descriptor type. We will eventually need to handle
//! more types.
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//!
//! ## Design notes
//!
//! The crate is derived into three main parts. In the (private) `parse`
//! module, we have the generic code that we use to parse different
//! kinds of network documents. In the [`types`] module we have
//! implementations for parsing specific data structures that are used
//! inside directory documents. Finally, the [`doc`] module defines
//! the parsers for the documents themselves.
//!
//! # Features
//!
//! `build_docs`: enable code to construct the objects representing different
//! network documents.
//!
//! `routerdesc`: enable support for the "router descriptor" document type, which
//! is needed by bridge clients and relays.
//!
//! `ns-consensus`: enable support for the "ns consensus" document type, which
//! some relays cache and serve.
//!
//! # Caveat haxxor: limitations and infelicities
//!
//! TODO: This crate requires that all of its inputs be valid UTF-8:
//! This is fine only if we assume that proposal 285 is implemented in
//! mainline Tor.
//!
//! TODO: This crate has several pieces that could probably be split out
//! into other smaller cases, including handling for version numbers
//! and exit policies.
//!
//! TODO: Many parts of this crate that should eventually be public
//! aren't.
//!
//! TODO: this crate needs far more tests!
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,14 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `tor-persist`: Persistent data storage for use with Tor.
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//!
//! For now, users should construct storage objects directly with (for
//! example) [`FsStateMgr::from_path_and_mistrust()`], but use them primarily via the
//! interfaces of the [`StateMgr`] trait.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,104 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! Implementations for the core Tor protocol
//!
//! # Overview
//!
//! The `tor-proto` crate lies at the core of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//! Most people shouldn't use this crate directly,
//! since its APIs are needlessly low-level for most purposes, and it is
//! easy to misuse them in an insecure or privacy-violating way.
//!
//! Most people should use the [`arti-client`] crate instead. This crate is
//! of interest mainly for those that want to access the Tor protocols at
//! a low level.
//!
//! ## Core concepts
//!
//! At its essence, Tor makes connections called "channels" to other
//! Tor instances. These channels are implemented using TLS. Each of
//! these channels multiplexes a number of anonymized multihop
//! "circuits" that act as reliable transports for "relay messages"
//! that are sent between clients and the different relays on the
//! circuits. Finally, each circuit multiplexes a number of "streams",
//! each corresponding roughly to an application-level request.
//!
//! This crate implements the logic, protocols, and cryptography that
//! implement these [`channel::Channel`]s, [`circuit::ClientCirc`]s, and
//! [`stream::DataStream`]s. It uses rust async code and future-related
//! traits, and is intended to work with (nearly) any executor
//! implementation that complies with the futures API. It should also
//! work with nearly any TLS implementation that exposes AsyncRead and
//! AsyncWrite traits.
//!
//! ## Not in this crate
//!
//! This crate does _not_ implement higher level protocols, like onion
//! services or the Tor directory protocol, that are based on the Tor
//! protocol here. Nor does it decide _when_, _how_, or _where_ to
//! build channels and circuits: that's the role of higher-level crates.
//!
//! This crate also has no support for timeouts, so every network
//! operation here has the potential to block the current task
//! indefinitely. Timeouts are another necessary piece that gets
//! added at a higher level.
//!
//! In order to create channels and circuits, you'll need to know
//! about some Tor relays, and expose their information via
//! [`tor_linkspec::ChanTarget`] and [`tor_linkspec::CircTarget`].
//! Currently, the [`tor-netdir`] crate is the easiest way to do so.
//!
//! For an example of this crate in action, see the [`arti-client`]
//! library, or the `arti` CLI.
//!
//! # Design notes
//!
//! This crate's APIs are structured to limit usage of an asynchronous runtime:
//! It doesn't launch tasks or create timers except when necessary.
//!
//! To the extent possible, this crate avoids doing public-key
//! cryptography in the same functions it uses for network activity.
//! This makes it easier for higher-level code to parallelize or yield
//! around public-key operations.
//!
//! Also, this crate tries to avoid knowing or encoding information about what
//! its objects (channels, circuits, streams) are "used for". That is, whenever
//! possible, we encode _how an object should behave_, not _the reason that it
//! should behave that way_. For example, the `Circuit` object in this crate
//! remembers the path through which the circuit was built, but _not_ the
//! purpose that the circuit serves, or what it may be used for. It's the
//! responsibility of other crates to enforce that kind of rule.
//!
//! Why separate behavior from purpose in this way?
//! We do so in order to prevent a kind of logical overloading that we ran into
//! with the C tor implementation, where usage information is _not_ separate
//! from behavioral settings. Since usage information is available, at all
//! points in the codebase the C tor code has converged in many places on
//! complex logic involving that usage information in order to set individual
//! behaviors. Because of that, adding a new kinds usage or behavior in C tor
//! has become quite complex. We're trying to avoid that kind of complexity in
//! Arti.
//!
//! # Limitations
//!
//! This is all a work in progress, and will need severe refactoring
//! before it's done.
//!
//! This is a client-only implementation; there is no support the
//! operations that Relays need.
//!
//! There are too many missing features to list.
//!
//! There isn't enough documentation or examples.
//!
//! This crate was my first attempt to use async in rust, and is probably
//! pretty kludgy.
//!
//! I bet that there are deadlocks somewhere in this code. I fixed
//! all the ones I could find or think of, but it would be great to
//! find a good way to eliminate every lock that we have.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,39 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! Implementation of Tor's "subprotocol versioning" feature.
//!
//! # Overview
//!
//! The Tor system is built out of numerous "subprotocols" that are
//! versioned more or less independently. The `tor-protover` crate
//! implements parsing and handling for these subprotocol versions, so
//! that different Tor instances know which parts of the protocol
//! they support.
//!
//! Subprotocol versions are also used to determine which versions of
//! the protocol are required to connect to the network (or just
//! recommended).
//!
//! For more details, see [tor-spec.txt](https://spec.torproject.org/tor-spec)
//! section 9.
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//! It's unlikely to be of general interest
//! unless you are writing a Tor implementation, or a program that
//! needs to examine fine-grained details of the Tor network.
//!
//! ## Design notes
//!
//! We're giving `tor-protover` its own crate within arti because it
//! needs to be used to multiple higher level crates that do not
//! themselves depend on one another. (For example, [`tor-proto`]
//! needs to know which variant of a subprotocol can be used with a
//! given relay, whereas [`tor-netdoc`] needs to parse lists of
//! subprotocol versions from directory documents. Eventually,
//! [`arti-client`] will need to check its own list of supported
//! protocols against the required list in the consensus.)
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,39 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `tor-ptmgr`: Manage a set of anti-censorship pluggable transports.
//!
//! # Overview
//!
//! This crate is part of [Arti](https://gitlab.torproject.org/tpo/core/arti/),
//! a project to implement [Tor](https://www.torproject.org/) in Rust.
//!
//! In Tor, a "transport" is a mechanism used to avoid censorship by disguising
//! the Tor protocol as some other kind of traffic.
//!
//! A "pluggable transport" is one that is not implemented by default as part of
//! the Tor protocol, but which can instead be added later on by the packager or
//! the user. Pluggable transports are typically provided as external binaries
//! that implement a SOCKS proxy, along with certain other configuration
//! protocols.
//!
//! This crate provides a means to manage a set of configured pluggable
//! transports
//!
//! # Limitations
//!
//! TODO pt-client: Currently, the APIs for this crate make it quite
//! tor-specific. Notably, it can only return Channels! It would be good
//! instead to adapt it so that it was more generally useful by other projects
//! that want to use pluggable transports in rust. For now, I have put the
//! Tor-channel-specific stuff behind a `tor-channel-factory` feature, but there
//! are no APIs for using PTs without that feature currently. That should
//! change.
//!
//! TODO pt-client: Nothing in this crate is actually implemented yet.
//!
//! TODO pt-client: The first version of this crate will probably only conform
//! to the old Tor pluggable transport protocol, and not to more recent variants
//! as documented at `pluggabletransports.info`
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,144 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! Compatibility between different async runtimes for Arti.
//!
//! # Overview
//!
//! Rust's support for asynchronous programming is powerful, but still
//! a bit immature: there are multiple powerful runtimes you can use,
//! but they do not expose a consistent set of interfaces.
//!
//! The [`futures`] API abstracts much of the differences among these
//! runtime libraries, but there are still areas where no standard API
//! yet exists, including:
//! - Network programming.
//! - Time and delays.
//! - Launching new tasks
//! - Blocking until a task is finished.
//!
//! Additionally, the `AsyncRead` and `AsyncWrite` traits provide by
//! [`futures`] are not the same as those provided by `tokio`, and
//! require compatibility wrappers to use.
//!
//! To solve these problems, the `tor-rtcompat` crate provides a set
//! of traits that represent a runtime's ability to perform these
//! tasks, along with implementations for these traits for the `tokio`
//! and `async-std` runtimes. In the future we hope to add support
//! for other runtimes as needed.
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//! As such, it does not currently include (or
//! plan to include) any functionality beyond what Arti needs to
//! implement Tor.
//!
//! We hope that in the future this crate can be replaced (or mostly
//! replaced) with standardized and general-purpose versions of the
//! traits it provides.
//!
//! # Using `tor-rtcompat`
//!
//! The `tor-rtcompat` crate provides several traits that
//! encapsulate different runtime capabilities.
//!
//! * A runtime is a [`BlockOn`] if it can block on a future.
//! * A runtime is a [`SleepProvider`] if it can make timer futures that
//! become Ready after a given interval of time.
//! * A runtime is a [`TcpProvider`] if it can make and receive TCP
//! connections
//! * A runtime is a [`TlsProvider`] if it can make TLS connections.
//!
//! For convenience, the [`Runtime`] trait derives from all the traits
//! above, plus [`futures::task::Spawn`] and [`Send`].
//!
//! You can get a [`Runtime`] in several ways:
//!
//! * If you already have an asynchronous backend (for example, one
//! that you built with tokio by running with
//! `#[tokio::main]`), you can wrap it as a [`Runtime`] with
//! [`PreferredRuntime::current()`].
//!
//! * If you want to construct a default runtime that you won't be
//! using for anything besides Arti, you can use [`PreferredRuntime::create()`].
//!
//! Both of the above methods use the "preferred runtime", which is usually Tokio.
//! However, changing the set of Cargo features available can affect this; see
//! [`PreferredRuntime`] for more.
//!
//! * If you want to use a runtime with an explicitly chosen backend,
//! name its type directly as [`async_std::AsyncStdNativeTlsRuntime`],
//! [`async_std::AsyncStdRustlsRuntime`], [`tokio::TokioNativeTlsRuntime`],
//! or [`tokio::TokioRustlsRuntime`]. To construct one of these runtimes,
//! call its `create()` method. Or if you have already constructed a
//! Tokio runtime that you want to use, you can wrap it as a
//! [`Runtime`] explicitly with `current()`.
//!
//! # Advanced usage: implementing runtimes yourself
//!
//! You might want to implement some of the traits above (especially [`TcpProvider`] and
//! [`TlsProvider`]) if you're embedding Arti, and want more control over the resources it uses.
//! For example, you might want to perform actions when TCP connections open and close, replace the
//! TLS stack with your own, or proxy TCP connections over your own custom transport.
//!
//! This can be more easily accomplished using the [`CompoundRuntime`] type, which lets you
//! create a [`Runtime`] from various implementors of the various traits (which don't all need to
//! be the same).
//!
//! See [`arti-client/examples/hook-tcp.rs`](https://gitlab.torproject.org/tpo/core/arti/-/blob/main/crates/arti-client/examples/hook-tcp.rs)
//! for a full example of this.
//!
//! # Cargo features
//!
//! Features supported by this crate:
//!
//! * `tokio` -- build with [Tokio](https://tokio.rs/) support
//! * `async-std` -- build with [async-std](https://async.rs/) support
//! * `native-tls` -- build with the [native-tls](https://github.com/sfackler/rust-native-tls)
//! crate for TLS support
//! * `static` -- link the native TLS library statically (enables the `vendored` feature of the
//! `native-tls` crate).
//! * `rustls` -- build with the [rustls](https://github.com/rustls/rustls) crate for TLS support. Note that `rustls` uses the `ring` crate, which uses
//! the old (3BSD/SSLEay) OpenSSL license, which may introduce licensing
//! compatibility issues.
//!
//! By default, *this* crate doesn't enable any features. However, you're almost certainly
//! using this as part of the `arti-client` crate, which will enable `tokio` and `native-tls` in
//! its default configuration.
//!
//! # Design FAQ
//!
//! ## Why support `async_std`?
//!
//! Although Tokio currently a more popular and widely supported
//! asynchronous runtime than `async_std` is, we believe that it's
//! critical to build Arti against multiple runtimes.
//!
//! By supporting multiple runtimes, we avoid making tokio-specific
//! assumptions in our code, which we hope will make it easier to port
//! to other environments (like WASM) in the future.
//!
//! ## Why a `Runtime` trait, and not a set of functions?
//!
//! We could simplify this code significantly by removing most of the
//! traits it exposes, and instead just exposing a single
//! implementation. For example, instead of exposing a
//! [`BlockOn`] trait to represent blocking until a task is
//! done, we could just provide a single global `block_on` function.
//!
//! That simplification would come at a cost, however. First of all,
//! it would make it harder for us to use Rust's "feature" system
//! correctly. Current features are supposed to be _additive only_,
//! but if had a single global runtime, then support for different
//! backends would be _mutually exclusive_. (That is, you couldn't
//! have both the tokio and async-std features building at the same
//! time.)
//!
//! Secondly, much of our testing in the rest of Arti relies on the
//! ability to replace [`Runtime`]s. By treating a runtime as an
//! object, we can override a runtime's view of time, or of the
//! network, in order to test asynchronous code effectively.
//! (See the [`tor-rtmock`] crate for examples.)
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -58,8 +58,9 @@ Or, you could solve both of these problems by using `tor-rtmock`
to replace the internet _and_ the passage of time. (Here we're only
replacing the internet.)
```rust
#
```rust,no_run
# async fn say_hi<R,A>(runtime: R, addr: A) -> Result<(), ()> { Ok(()) }
# // TODO this test hangs for some reason? Fix it and remove no_run above
use tor_rtmock::{MockSleepRuntime,MockNetRuntime,net::MockNetwork};
use tor_rtcompat::{TcpProvider,TcpListener};
use futures::io::AsyncReadExt;

View File

@ -1,113 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! Support for mocking with `tor-rtcompat` asynchronous runtimes.
//!
//! # Overview
//!
//! The `tor-rtcompat` crate defines a `Runtime` trait that represents
//! most of the common functionality of . This crate provides mock
//! implementations that override a `Runtime`, in whole or in part,
//! for testing purposes.
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//! It is used to write tests for higher-level
//! crates in Arti that rely on asynchronous runtimes.
//!
//! This crate should only be used for writing tests.
//!
//! Currently, we support mocking the passage of time (via
//! [`MockSleepRuntime`]), and impersonating the internet (via
//! [`MockNetRuntime`]).
//!
//! # Examples
//!
//! Suppose you've written a function that relies on making a
//! connection to the network and possibly timing out:
//!
//! ```
//! use tor_rtcompat::{Runtime,SleepProviderExt};
//! use std::{net::SocketAddr, io::Result, time::Duration, io::Error};
//! use futures::io::AsyncWriteExt;
//!
//! async fn say_hi(runtime: impl Runtime, addr: &SocketAddr) -> Result<()> {
//! let delay = Duration::new(5,0);
//! runtime.timeout(delay, async {
//! let mut conn = runtime.connect(addr).await?;
//! conn.write_all(b"Hello world!\r\n").await?;
//! conn.close().await?;
//! Ok::<_,Error>(())
//! }).await??;
//! Ok(())
//! }
//! ```
//!
//! But how should you test this function?
//!
//! You might try connecting to a well-known website to test the
//! connection case, and to a well-known black hole to test the
//! timeout case... but that's a bit undesirable. Your tests might be
//! running in a container with no internet access; and even if they
//! aren't, it isn't so great for your tests to rely on the actual
//! state of the internet. Similarly, if you make your timeout too long,
//! your tests might block for a long time; but if your timeout is too short,
//! the tests might fail on a slow machine or on a slow network.
//!
//! Or, you could solve both of these problems by using `tor-rtmock`
//! to replace the internet _and_ the passage of time. (Here we're only
//! replacing the internet.)
//!
//! ```
//! # use tor_rtcompat::{Runtime,SleepProviderExt};
//! # use std::{net::SocketAddr, io::Result, time::Duration, io::Error};
//! # use futures::io::AsyncWriteExt;
//! #
//! # async fn say_hi(runtime: impl Runtime, addr: &SocketAddr) -> Result<()> {
//! # let delay = Duration::new(5,0);
//! # runtime.timeout(delay, async {
//! # let mut conn = runtime.connect(addr).await?;
//! # conn.write_all(b"Hello world!\r\n").await?;
//! # conn.close().await?;
//! # dbg!("okay apparently");
//! # Ok::<_,Error>(())
//! # }).await??;
//! # Ok(())
//! # }
//! use tor_rtmock::{MockSleepRuntime,MockNetRuntime,net::MockNetwork};
//! use tor_rtcompat::{TcpProvider,TcpListener};
//! use futures::io::AsyncReadExt;
//!
//! tor_rtcompat::test_with_all_runtimes!(|rt| async move {
//!
//! let addr1 = "198.51.100.7".parse().unwrap();
//! let addr2 = "198.51.100.99".parse().unwrap();
//! let sockaddr = "198.51.100.99:101".parse().unwrap();
//!
//! // Make a runtime that pretends that we are at the first address...
//! let fake_internet = MockNetwork::new();
//! let rt1 = fake_internet.builder().add_address(addr1).runtime(rt.clone());
//! // ...and one that pretends we're listening at the second address.
//! let rt2 = fake_internet.builder().add_address(addr2).runtime(rt);
//! let listener = rt2.listen(&sockaddr).await.unwrap();
//!
//! // Now we can test our function!
//! let (result1,output) = futures::join!(
//! say_hi(rt1, &sockaddr),
//! async {
//! let (mut conn,addr) = listener.accept().await.unwrap();
//! assert_eq!(addr.ip(), addr1);
//! let mut output = Vec::new();
//! conn.read_to_end(&mut output).await.unwrap();
//! output
//! });
//!
//! assert!(result1.is_ok());
//! assert_eq!(&output[..], b"Hello world!\r\n");
//! });
//! ```
//!
//! (TODO: Add an example for the timeout case.)
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,62 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! Implements SOCKS in the flavors provided by Tor.
//!
//! # Overview
//!
//! SOCKS is an old and somewhat janky protocol for telling a TCP
//! proxy where to connect. Versions 4, 4a, and 5 are sometimes
//! encountered in the wild.
//!
//! The `tor-socksproto` crate tries to hide the actual details of the
//! protocol, and expose a stateful handshake type that eventually
//! provides a [`SocksRequest`] or an error. It is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//! At present, it is only used to provide a
//! SOCKS proxy _over_ the Tor network, but eventually it may be used
//! to implement support for connecting to the Tor network over a
//! SOCKS proxy.
//!
//! This crate may be a good choice for you if you need a SOCKS
//! implementation that "behaves like Tor", but otherwise it is
//! probably better to use some other SOCKS crate.
//!
//! For more information about SOCKS:
//!
//! * SOCKS5 (which is preferred) is specified in
//! [RFC 1928](https://tools.ietf.org/html/rfc1928), and see also
//! [RFC 1929](https://tools.ietf.org/html/rfc1929) for
//! Username/Password authentication in SOCKS5.
//! * [The wikipedia article](https://en.wikipedia.org/wiki/SOCKS)
//! is the best surviving documentation for SOCKS4 and SOCKS4a.
//! * See
//! [socks-extensions.txt](https://spec.torproject.org/socks-extensions)
//! for a description of Tor's extensions and restrictions on the
//! SOCKS protocol.
//!
//! ## Design notes
//!
//! Arti uses this crate instead of some other SOCKS implementation,
//! for two reasons:
//!
//! * First, because we need to support Tor SOCKS extensions.
//! * Second, and because we sometimes need to see particular details
//! of the individual handshakes that most other SOCKS
//! implementations don't expose. (For example, if we are told to
//! connect to a raw IP address, the type of the handshake can help
//! us guess whether that IP address came from a DNS responsein
//! which case we should warn about a possible DNS leak.)
//!
//! Currently, `tor-socksproto` does no networking code: it _only_
//! implements the server (proxy) side of the SOCKS handshake by
//! handling a series of bytes. We may (or may not) want to add
//! network functionality to this crate or elsewhere in the future.
//! We'll definitely want to add client functionality.
//!
//! Possibly, this approach will prove useful for other uses. If it
//! does, We can put the tor-only functionality behind a Cargo build
//! feature, so that others can use this crate more safely.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -1,21 +1,5 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
//! `tor-units` -- Safe wrappers for primitive numeric types.
//!
//! # Overview
//!
//! This crate is part of
//! [Arti](https://gitlab.torproject.org/tpo/core/arti/), a project to
//! implement [Tor](https://www.torproject.org/) in Rust.
//! It provides safe wrappers for primitive numeric wrappers used in
//! other parts of Arti.
//! In particular, it provides:
//! * a bounded i32 with both checked and clamping constructors,
//! * an integer milliseconds wrapper with conversion to [`Duration`]
//! * an integer seconds wrapper with conversion to [`Duration`]
//! * a percentage wrapper, to prevent accidental failure
//! to divide by 100.
//! * a SendMeVersion which can be compared only.
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![cfg_attr(not(ci_arti_stable), allow(renamed_and_removed_lints))]
#![cfg_attr(not(ci_arti_nightly), allow(unknown_lints))]

View File

@ -12,7 +12,6 @@
* cargo upgrade --dry-run --workspace --skip-compatible
* ./maint/cargo_audit
* ./maint/check_licenses
* ./maint/readmes
(Note that not all of the above will make changes on their own; you'll
need to understand the output and decide what to do.)

View File

@ -1,12 +0,0 @@
#!/bin/bash
set -euo pipefail
cd "$(dirname "$0")/.."
for subcargo in crates/*/Cargo.toml ; do
cd "$(dirname "$subcargo")"
cargo readme > README.md
cd ../..
done