summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/arti/Cargo.toml2
-rw-r--r--crates/tor-circmgr/Cargo.toml2
-rw-r--r--crates/tor-circmgr/src/hspool.rs67
-rw-r--r--crates/tor-circmgr/src/path/hspath.rs53
4 files changed, 100 insertions, 24 deletions
diff --git a/crates/arti/Cargo.toml b/crates/arti/Cargo.toml
index 2f1b5c61c..1809e4e3b 100644
--- a/crates/arti/Cargo.toml
+++ b/crates/arti/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "arti"
-version = "1.2.2"
+version = "1.2.3"
authors = ["The Tor Project, Inc.", "Nick Mathewson <[email protected]>"]
edition = "2021"
rust-version = "1.70"
diff --git a/crates/tor-circmgr/Cargo.toml b/crates/tor-circmgr/Cargo.toml
index 418a99fc6..819828046 100644
--- a/crates/tor-circmgr/Cargo.toml
+++ b/crates/tor-circmgr/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "tor-circmgr"
-version = "0.18.0"
+version = "0.18.1"
authors = ["The Tor Project, Inc.", "Nick Mathewson <[email protected]>"]
edition = "2021"
rust-version = "1.70"
diff --git a/crates/tor-circmgr/src/hspool.rs b/crates/tor-circmgr/src/hspool.rs
index ace838e22..6622c7307 100644
--- a/crates/tor-circmgr/src/hspool.rs
+++ b/crates/tor-circmgr/src/hspool.rs
@@ -15,10 +15,10 @@ use futures::{task::SpawnExt, StreamExt, TryFutureExt};
use once_cell::sync::OnceCell;
use tor_error::debug_report;
use tor_error::{bad_api_usage, internal};
-use tor_linkspec::{CircTarget, OwnedCircTarget};
+use tor_linkspec::{CircTarget, HasRelayIds as _, OwnedCircTarget, RelayIdSet};
use tor_netdir::{NetDir, NetDirProvider, Relay};
-use tor_proto::circuit::{self, ClientCirc};
-use tor_relay_selection::{LowLevelRelayPredicate, RelayExclusion};
+use tor_proto::circuit::{self, CircParameters, ClientCirc};
+use tor_relay_selection::{LowLevelRelayPredicate, RelayExclusion, RelaySelector, RelayUsage};
use tor_rtcompat::{
scheduler::{TaskHandle, TaskSchedule},
Runtime, SleepProviderExt,
@@ -304,6 +304,20 @@ impl<R: Runtime> HsCircPool<R> {
.into());
}
+ let params = crate::DirInfo::from(netdir).circ_params();
+ self.extend_circ(circ, params, target).await
+ }
+
+ /// Try to extend a circuit to the specified target hop.
+ async fn extend_circ<T>(
+ &self,
+ circ: HsCircStub,
+ params: CircParameters,
+ target: T,
+ ) -> Result<Arc<ClientCirc>>
+ where
+ T: CircTarget,
+ {
// Estimate how long it will take to extend it one more hop, and
// construct a timeout as appropriate.
let n_hops = circ.n_hops();
@@ -315,7 +329,6 @@ impl<R: Runtime> HsCircPool<R> {
);
// Make a future to extend the circuit.
- let params = crate::DirInfo::from(netdir).circ_params();
let extend_future = circ
.extend_ntor(&target, &params)
.map_err(|error| Error::Protocol {
@@ -425,7 +438,7 @@ impl<R: Runtime> HsCircPool<R> {
};
// Return the circuit we found before, if any.
if let Some(circuit) = found_usable_circ {
- return self.maybe_extend_stub_circuit(circuit, kind);
+ return self.maybe_extend_stub_circuit(netdir, circuit, kind).await;
}
// TODO: There is a possible optimization here. Instead of only waiting
@@ -443,9 +456,10 @@ impl<R: Runtime> HsCircPool<R> {
}
/// Return a circuit of the specified `kind`, built from `circuit`.
- fn maybe_extend_stub_circuit(
+ async fn maybe_extend_stub_circuit(
&self,
- mut circuit: HsCircStub,
+ netdir: &NetDir,
+ circuit: HsCircStub,
kind: HsCircStubKind,
) -> Result<HsCircStub> {
if !self.vanguards_enabled() {
@@ -454,16 +468,49 @@ impl<R: Runtime> HsCircPool<R> {
match (circuit.kind, kind) {
(HsCircStubKind::Stub, HsCircStubKind::Extended) => {
- // TODO HS-VANGUARDS: if full vanguards are enabled and the circuit we got is STUB,
+ debug!("Wanted STUB+ circuit, but got STUB; extending by 1 hop...");
+ let params = CircParameters::default();
+ let usage = RelayUsage::middle_relay(Some(&RelayUsage::middle_relay(None)));
+ let circ_path = circuit.circ.path_ref();
+
+ // A STUB circuit is a 3-hop circuit.
+ debug_assert_eq!(circ_path.hops().len(), 3);
+
+ // Like in VanguardHsPathBuilder::pick_path, we only want to exclude the L2 and L3
+ // guards (so we skip over the guard)
+ let skip_n = 1;
+ let mut exclude_ids = RelayIdSet::new();
+ for hop in circ_path
+ .iter()
+ .skip(skip_n)
+ .flat_map(|hop| hop.as_chan_target())
+ {
+ exclude_ids.extend(hop.identities().map(|id| id.to_owned()));
+ }
+
+ let exclusion = RelayExclusion::exclude_identities(exclude_ids);
+ let selector = RelaySelector::new(usage, exclusion);
+ let target = {
+ let mut rng = rand::thread_rng();
+ let (relay, info) = selector.select_relay(&mut rng, netdir);
+ relay.ok_or_else(|| Error::NoRelay {
+ path_kind: "vanguard STUB+",
+ role: "final hop",
+ problem: info.to_string(),
+ })?
+ };
+
+ // If full vanguards are enabled and the circuit we got is STUB,
// we need to extend it by another hop to make it STUB+ before returning it
- circuit.kind = kind;
+ let circ = self.extend_circ(circuit, params, target).await?;
- Ok(circuit)
+ Ok(HsCircStub { circ, kind })
}
(HsCircStubKind::Extended, HsCircStubKind::Stub) => {
Err(internal!("wanted a STUB circuit, but got STUB+?!").into())
}
_ => {
+ trace!("Wanted {kind} circuit, got {}", circuit.kind);
// Nothing to do: the circuit stub we got is of the kind we wanted
Ok(circuit)
}
diff --git a/crates/tor-circmgr/src/path/hspath.rs b/crates/tor-circmgr/src/path/hspath.rs
index c9ec30fd8..c3e3e3bb9 100644
--- a/crates/tor-circmgr/src/path/hspath.rs
+++ b/crates/tor-circmgr/src/path/hspath.rs
@@ -43,9 +43,12 @@
// TODO (#1339): we should be consistent with our terminology.
use rand::Rng;
+use tor_error::internal;
use tor_linkspec::OwnedChanTarget;
use tor_netdir::{NetDir, Relay};
-use tor_relay_selection::{RelayExclusion, RelaySelectionConfig, RelaySelector, RelayUsage};
+use tor_relay_selection::{
+ RelayExclusion, RelaySelectionConfig, RelaySelector, RelayUsage, SelectionInfo,
+};
use crate::{hspool::HsCircStubKind, Error, Result};
@@ -222,13 +225,20 @@ impl VanguardHsPathBuilder {
// * the L2 vanguard, because it cannot be selected again as an L3 vanguard
// (a relay won't let you extend the circuit to itself).
// * the guard, because relays won't let you extend the circuit to their previous hop
- let neighbor_exclusion = exclude_identities(&[&l2_guard, &l1_guard]);
+ let l1_l2_exclusion = exclude_identities(&[&l2_guard, &l1_guard]);
let mut hops = vec![l1_guard, l2_guard.clone()];
+ let mode = vanguards.mode();
+
+ let extra_hop_err = |info: SelectionInfo| Error::NoRelay {
+ path_kind: self.path_kind(),
+ role: "extra hop",
+ problem: info.to_string(),
+ };
// If needed, select an L3 vanguard too
- if vanguards.mode() == VanguardMode::Full {
+ if mode == VanguardMode::Full {
let l3_guard: MaybeOwnedRelay = vanguards
- .select_vanguard(rng, netdir, Layer::Layer3, &neighbor_exclusion)?
+ .select_vanguard(rng, netdir, Layer::Layer3, &l1_l2_exclusion)?
.into();
hops.push(l3_guard.clone());
@@ -239,22 +249,41 @@ impl VanguardHsPathBuilder {
// TODO: this usage has need_stable = true, but we probably
// don't necessarily need a stable relay here.
let usage = RelayUsage::middle_relay(None);
- let neighbor_exclusion = exclude_identities(&[&l2_guard, &l3_guard]);
+ let l2_l3_exclusion = exclude_identities(&[&l2_guard, &l3_guard]);
// We exclude
// * the L3 vanguard, because it cannot be selected again as the following
// extra hop (a relay won't let you extend the circuit to itself).
// * the L2 vanguard, because relays won't let you extend the circuit to their previous hop
- let selector = RelaySelector::new(usage, neighbor_exclusion);
+ let selector = RelaySelector::new(usage, l2_l3_exclusion);
let (extra_hop, info) = selector.select_relay(rng, netdir);
- let extra_hop = extra_hop.ok_or_else(|| Error::NoRelay {
- path_kind: self.path_kind(),
- role: "extra hop",
- problem: info.to_string(),
- })?;
-
+ let extra_hop = extra_hop.ok_or_else(|| extra_hop_err(info))?;
hops.push(MaybeOwnedRelay::from(extra_hop));
}
+ } else {
+ // Extend the circuit to a third, arbitrarily chosen hop, excluding the L1 and L2
+ // guards as before.
+ let usage = RelayUsage::middle_relay(None);
+ let selector = RelaySelector::new(usage, l1_l2_exclusion);
+
+ let (extra_hop, info) = selector.select_relay(rng, netdir);
+ let extra_hop = extra_hop.ok_or_else(|| extra_hop_err(info))?;
+ hops.push(MaybeOwnedRelay::from(extra_hop));
+ }
+
+ match (mode, self.0) {
+ (VanguardMode::Lite, _) => debug_assert_eq!(hops.len(), 3),
+ (VanguardMode::Full, HsCircStubKind::Stub) => debug_assert_eq!(hops.len(), 3),
+ (VanguardMode::Full, HsCircStubKind::Extended) => debug_assert_eq!(hops.len(), 4),
+ (VanguardMode::Disabled, _) => {
+ return Err(internal!(
+ "Called VanguardHsPathBuilder::pick_path(), but vanguards are disabled?!"
+ )
+ .into());
+ }
+ (_, _) => {
+ return Err(internal!("Unsupported vanguard mode {mode}").into());
+ }
}
Ok((TorPath::new_multihop_from_maybe_owned(hops), mon, usable))