1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
//! 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 explicitly avoid any usage of
//! an asynchronous runtime: It doesn't launch tasks or include
//! timeouts. Those are done at a higher level in Arti, via the
//! [`tor-rtcompat`] crate.
//!
//! 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.
//!
//! # 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.
//!
//! This crate doesn't work with rusttls because of a limitation in the
//! webpki crate.
#![deny(missing_docs)]
#![warn(noop_method_call)]
#![deny(unreachable_pub)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::cargo_common_metadata)]
#![deny(clippy::cast_lossless)]
#![deny(clippy::checked_conversions)]
#![warn(clippy::clone_on_ref_ptr)]
#![warn(clippy::cognitive_complexity)]
#![deny(clippy::debug_assert_with_mut_call)]
#![deny(clippy::exhaustive_enums)]
#![deny(clippy::exhaustive_structs)]
#![deny(clippy::expl_impl_clone_on_copy)]
#![deny(clippy::fallible_impl_from)]
#![deny(clippy::implicit_clone)]
#![deny(clippy::large_stack_arrays)]
#![warn(clippy::manual_ok_or)]
#![deny(clippy::missing_docs_in_private_items)]
#![deny(clippy::missing_panics_doc)]
#![warn(clippy::needless_borrow)]
#![warn(clippy::needless_pass_by_value)]
#![warn(clippy::option_option)]
#![warn(clippy::rc_buffer)]
#![deny(clippy::ref_option_ref)]
#![warn(clippy::trait_duplication_in_bounds)]
#![deny(clippy::unnecessary_wraps)]
#![warn(clippy::unseparated_literal_suffix)]
#![deny(clippy::unwrap_used)]
pub mod channel;
pub mod circuit;
mod crypto;
pub mod stream;
mod util;
pub use util::err::Error;
/// A vector of bytes that gets cleared when it's dropped.
type SecretBytes = zeroize::Zeroizing<Vec<u8>>;
/// A Result type for this crate.
pub type Result<T> = std::result::Result<T, Error>;