diff options
author | gabi-250 <gabi@torproject.org> | 2024-03-14 13:00:28 +0000 |
---|---|---|
committer | gabi-250 <gabi@torproject.org> | 2024-03-14 13:00:28 +0000 |
commit | e3a8e918228a62a64e7cc0bf1ff717eb875f59f2 (patch) | |
tree | 344fea1e2d519572af0d0c26a52d4ef0946b4c7e | |
parent | 6b120ec2117b8b0dfb5f0daa1746ec532cf3ad3a (diff) | |
parent | fc7c647f05a3f0ddde556bb065d357d6fc842211 (diff) | |
download | arti-1333-ensure-that-transport-configuration-has-tests-in-arti-cfg.tar.gz arti-1333-ensure-that-transport-configuration-has-tests-in-arti-cfg.zip |
Merge branch 'exitpath-onion-svc' into 'main'1333-ensure-that-transport-configuration-has-tests-in-arti-cfg
tor-circmgr: Add HsPathBuilder for building onion service paths
See merge request tpo/core/arti!2038
-rw-r--r-- | .gitlab-ci.yml | 3 | ||||
-rw-r--r-- | crates/tor-circmgr/src/path.rs | 181 | ||||
-rw-r--r-- | crates/tor-circmgr/src/path/exitpath.rs | 237 | ||||
-rw-r--r-- | crates/tor-circmgr/src/path/hspath.rs | 124 | ||||
-rw-r--r-- | crates/tor-circmgr/src/usage.rs | 10 | ||||
-rw-r--r-- | tests/shadow/README.md | 2 |
6 files changed, 349 insertions, 208 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 19f375594..1d47a83b0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -95,12 +95,13 @@ rust-latest: image: rust:bookworm script: - rustup show - - cargo build --locked --verbose --target x86_64-unknown-linux-gnu + - cargo check --locked --verbose --target x86_64-unknown-linux-gnu - cargo test --verbose --target x86_64-unknown-linux-gnu - rustup component add clippy - rustup show - cargo clippy --all-features --all-targets -- --cfg ci_arti_stable -D warnings - cargo build --verbose --release -p arti-bench --target x86_64-unknown-linux-gnu + - cargo build --locked --verbose --target x86_64-unknown-linux-gnu -p arti - ./maint/preserve target/x86_64-unknown-linux-gnu/debug/arti target/x86_64-unknown-linux-gnu/release/arti-bench after_script: - cargo clean diff --git a/crates/tor-circmgr/src/path.rs b/crates/tor-circmgr/src/path.rs index 2d91c4e26..36f27a3fc 100644 --- a/crates/tor-circmgr/src/path.rs +++ b/crates/tor-circmgr/src/path.rs @@ -5,16 +5,25 @@ pub mod dirpath; pub mod exitpath; +#[cfg(feature = "hs-common")] +pub mod hspath; -use tor_error::bad_api_usage; +use std::time::SystemTime; + +use rand::Rng; + +use tor_error::{bad_api_usage, internal}; #[cfg(feature = "geoip")] use tor_geoip::{CountryCode, HasCountryCode}; use tor_guardmgr::fallback::FallbackDir; -use tor_linkspec::{HasAddrs, HasRelayIds, OwnedChanTarget, OwnedCircTarget}; -use tor_netdir::Relay; +use tor_guardmgr::{GuardMgr, GuardMonitor, GuardUsable}; +use tor_linkspec::{HasAddrs, HasRelayIds, OwnedChanTarget, OwnedCircTarget, RelayIdSet}; +use tor_netdir::{NetDir, Relay}; +use tor_relay_selection::{RelayExclusion, RelaySelectionConfig, RelaySelector, RelayUsage}; +use tor_rtcompat::Runtime; use crate::usage::ExitPolicy; -use crate::Result; +use crate::{DirInfo, Error, PathConfig, Result}; /// A list of Tor relays through the network. pub struct TorPath<'a> { @@ -237,6 +246,170 @@ impl OwnedPath { } } +/// A path builder that builds multi-hop, anonymous paths. +trait AnonymousPathBuilder<'a> { + /// Return the relay to use as exit node. + fn chosen_exit(&self) -> Option<&Relay<'_>>; + + /// Return the "target" that every chosen relay must be able to share a circuit with with. + fn compatible_with(&self) -> Option<&OwnedChanTarget>; + + /// Return a short description of the path we're trying to build, + /// for error reporting purposes. + fn path_kind(&self) -> &'static str; + + /// Find a suitable exit node from either the chosen exit or from the network directory. + /// + /// Return the exit, along with the usage for a middle node corresponding + /// to this exit. + fn pick_exit<'s, R: Rng>( + &'s self, + rng: &mut R, + netdir: &'a NetDir, + guard_exclusion: RelayExclusion<'a>, + rs_cfg: &RelaySelectionConfig<'_>, + ) -> Result<(Relay<'a>, RelayUsage)>; +} + +/// Try to create and return a path corresponding to the requirements of +/// this builder. +fn pick_path<'s, 'a, B: AnonymousPathBuilder<'a>, R: Rng, RT: Runtime>( + builder: &B, + rng: &mut R, + netdir: DirInfo<'a>, + guards: Option<&GuardMgr<RT>>, + config: &PathConfig, + _now: SystemTime, +) -> Result<(TorPath<'a>, Option<GuardMonitor>, Option<GuardUsable>)> { + let netdir = match netdir { + DirInfo::Directory(d) => d, + _ => { + return Err(bad_api_usage!( + "Tried to build a multihop path without a network directory" + ) + .into()) + } + }; + let rs_cfg = config.relay_selection_config(); + + let chosen_exit = builder.chosen_exit(); + let path_is_fully_random = chosen_exit.is_none(); + + // TODO-SPEC: Because of limitations in guard selection, we have to + // pick the guard before the exit, which is not what our spec says. + let (guard, mon, usable) = match guards { + Some(guardmgr) => { + // TODO: Extract this section into its own function, and see + // what it can share with tor_relay_selection. + let mut b = tor_guardmgr::GuardUsageBuilder::default(); + b.kind(tor_guardmgr::GuardUsageKind::Data); + if let Some(exit_relay) = chosen_exit { + // TODO(nickm): Our way of building a family here is + // somewhat questionable. We're only adding the ed25519 + // identities of the exit relay and its family to the + // RelayId set. That's fine for now, since we will only use + // relays at this point if they have a known Ed25519 + // identity. But if in the future the ed25519 identity + // becomes optional, this will need to change. + let mut family = RelayIdSet::new(); + family.insert(*exit_relay.id()); + // TODO(nickm): See "limitations" note on `known_family_members`. + family.extend(netdir.known_family_members(exit_relay).map(|r| *r.id())); + b.restrictions() + .push(tor_guardmgr::GuardRestriction::AvoidAllIds(family)); + } + if let Some(avoid_target) = builder.compatible_with() { + let mut family = RelayIdSet::new(); + family.extend(avoid_target.identities().map(|id| id.to_owned())); + if let Some(avoid_relay) = netdir.by_ids(avoid_target) { + family.extend(netdir.known_family_members(&avoid_relay).map(|r| *r.id())); + } + b.restrictions() + .push(tor_guardmgr::GuardRestriction::AvoidAllIds(family)); + } + let guard_usage = b.build().expect("Failed while building guard usage!"); + let (guard, mut mon, usable) = guardmgr.select_guard(guard_usage)?; + let guard = if let Some(ct) = guard.as_circ_target() { + // This is a bridge; we will not look for it in the network directory. + MaybeOwnedRelay::from(ct.clone()) + } else { + // Look this up in the network directory: we expect to find a relay. + guard + .get_relay(netdir) + .ok_or_else(|| { + internal!( + "Somehow the guardmgr gave us an unlisted guard {:?}!", + guard + ) + })? + .into() + }; + if !path_is_fully_random { + // We were given a specific exit relay to use, and + // the choice of exit relay might be forced by + // something outside of our control. + // + // Therefore, we must not blame the guard for any failure + // to complete the circuit. + mon.ignore_indeterminate_status(); + } + (guard, Some(mon), Some(usable)) + } + None => { + let rs_cfg = config.relay_selection_config(); + let exclusion = match chosen_exit { + Some(r) => RelayExclusion::exclude_relays_in_same_family(&rs_cfg, vec![r.clone()]), + None => RelayExclusion::no_relays_excluded(), + }; + let selector = RelaySelector::new(RelayUsage::new_guard(), exclusion); + let (relay, info) = selector.select_relay(rng, netdir); + let relay = relay.ok_or_else(|| Error::NoRelay { + path_kind: builder.path_kind(), + role: "entry", + problem: info.to_string(), + })?; + + (MaybeOwnedRelay::from(relay), None, None) + } + }; + + let guard_exclusion = match &guard { + MaybeOwnedRelay::Relay(r) => RelayExclusion::exclude_relays_in_same_family( + &config.relay_selection_config(), + vec![r.clone()], + ), + MaybeOwnedRelay::Owned(ct) => RelayExclusion::exclude_channel_target_family( + &config.relay_selection_config(), + ct.as_ref(), + netdir, + ), + }; + + let (exit, middle_usage) = builder.pick_exit(rng, netdir, guard_exclusion.clone(), &rs_cfg)?; + + let mut family_exclusion = + RelayExclusion::exclude_relays_in_same_family(&rs_cfg, vec![exit.clone()]); + family_exclusion.extend(&guard_exclusion); + + let selector = RelaySelector::new(middle_usage, family_exclusion); + let (middle, info) = selector.select_relay(rng, netdir); + let middle = middle.ok_or_else(|| Error::NoRelay { + path_kind: builder.path_kind(), + role: "middle relay", + problem: info.to_string(), + })?; + + Ok(( + TorPath::new_multihop_from_maybe_owned(vec![ + guard, + MaybeOwnedRelay::from(middle), + MaybeOwnedRelay::from(exit), + ]), + mon, + usable, + )) +} + /// For testing: make sure that `path` is the same when it is an owned /// path. #[cfg(test)] diff --git a/crates/tor-circmgr/src/path/exitpath.rs b/crates/tor-circmgr/src/path/exitpath.rs index d54d82896..7b4b2829d 100644 --- a/crates/tor-circmgr/src/path/exitpath.rs +++ b/crates/tor-circmgr/src/path/exitpath.rs @@ -1,19 +1,20 @@ //! Code for building paths to an exit relay. -use super::{MaybeOwnedRelay, TorPath}; -use crate::{DirInfo, Error, PathConfig, Result, TargetPort}; -use rand::Rng; use std::time::SystemTime; -use tor_error::{bad_api_usage, internal}; -#[cfg(feature = "geoip")] -use tor_geoip::CountryCode; + +use rand::Rng; + +use super::{AnonymousPathBuilder, TorPath}; +use crate::path::pick_path; +use crate::{DirInfo, Error, PathConfig, Result, TargetPort}; + use tor_guardmgr::{GuardMgr, GuardMonitor, GuardUsable}; -use tor_linkspec::{HasRelayIds, OwnedChanTarget, RelayIdSet}; +use tor_linkspec::OwnedChanTarget; use tor_netdir::{NetDir, Relay}; -use tor_relay_selection::{ - RelayExclusion, RelayRestriction, RelaySelectionConfig, RelaySelector, RelayUsage, -}; +use tor_relay_selection::{RelayExclusion, RelaySelectionConfig, RelaySelector, RelayUsage}; use tor_rtcompat::Runtime; +#[cfg(feature = "geoip")] +use {tor_geoip::CountryCode, tor_relay_selection::RelayRestriction}; /// Internal representation of PathBuilder. enum ExitPathBuilderInner<'a> { @@ -41,11 +42,6 @@ enum ExitPathBuilderInner<'a> { strict: bool, }, - /// Request a path to any relay, even those that cannot exit. - // TODO: #785 may make this non-conditional. - #[cfg(feature = "hs-common")] - AnyRelayForOnionService, - /// Request a path that uses a given relay as exit node. ChosenExit(Relay<'a>), } @@ -119,24 +115,17 @@ impl<'a> ExitPathBuilder<'a> { } } - /// Create a new builder that will try to build a three-hop non-exit path - /// for use with the onion services protocols - /// that is compatible with being extended to an optional given relay. - /// - /// (The provided relay is _not_ included in the built path: we only ensure - /// that the path we build does not have any features that would stop us - /// extending it to that relay as a fourth hop.) - /// - /// TODO: This doesn't seem to belong in a type called ExitPathBuilder. - /// Perhaps we should rename ExitPathBuilder, split it into multiple types, - /// or move this method. - #[cfg(feature = "hs-common")] - pub(crate) fn for_onion_service(compatible_with: Option<OwnedChanTarget>) -> Self { - Self { - inner: ExitPathBuilderInner::AnyRelayForOnionService, - compatible_with, - require_stability: true, - } + /// Try to create and return a path corresponding to the requirements of + /// this builder. + pub fn pick_path<R: Rng, RT: Runtime>( + &self, + rng: &mut R, + netdir: DirInfo<'a>, + guards: Option<&GuardMgr<RT>>, + config: &PathConfig, + now: SystemTime, + ) -> Result<(TorPath<'a>, Option<GuardMonitor>, Option<GuardUsable>)> { + pick_path(self, rng, netdir, guards, config, now) } /// Create a new builder that will try to get an exit relay, but which @@ -155,13 +144,23 @@ impl<'a> ExitPathBuilder<'a> { self.require_stability = require_stability; self } +} - /// Find a suitable exit node from either the chosen exit or from the network directory. - /// - /// Return the exit, along with the usage for a middle node corresponding - /// to this exit. - fn pick_exit<R: Rng>( - &self, +impl<'a> AnonymousPathBuilder<'a> for ExitPathBuilder<'a> { + fn chosen_exit(&self) -> Option<&Relay<'_>> { + if let ExitPathBuilderInner::ChosenExit(e) = &self.inner { + Some(e) + } else { + None + } + } + + fn compatible_with(&self) -> Option<&OwnedChanTarget> { + self.compatible_with.as_ref() + } + + fn pick_exit<'s, R: Rng>( + &'s self, rng: &mut R, netdir: &'a NetDir, guard_exclusion: RelayExclusion<'a>, @@ -187,14 +186,6 @@ impl<'a> ExitPathBuilder<'a> { selector } - #[cfg(feature = "hs-common")] - ExitPathBuilderInner::AnyRelayForOnionService => { - // TODO: This usage is a bit convoluted, and some onion-service- - // related circuits don't need this much stability. - let usage = RelayUsage::middle_relay(Some(&RelayUsage::new_intro_point())); - RelaySelector::new(usage, guard_exclusion) - } - ExitPathBuilderInner::WantsPorts(wantports) => RelaySelector::new( RelayUsage::exit_to_all_ports(rs_cfg, wantports.clone()), guard_exclusion, @@ -217,153 +208,6 @@ impl<'a> ExitPathBuilder<'a> { Ok((relay, RelayUsage::middle_relay(Some(selector.usage())))) } - /// Try to create and return a path corresponding to the requirements of - /// this builder. - pub fn pick_path<R: Rng, RT: Runtime>( - &self, - rng: &mut R, - netdir: DirInfo<'a>, - guards: Option<&GuardMgr<RT>>, - config: &PathConfig, - _now: SystemTime, - ) -> Result<(TorPath<'a>, Option<GuardMonitor>, Option<GuardUsable>)> { - let netdir = match netdir { - DirInfo::Directory(d) => d, - _ => { - return Err(bad_api_usage!( - "Tried to build a multihop path without a network directory" - ) - .into()) - } - }; - let rs_cfg = config.relay_selection_config(); - - let chosen_exit = if let ExitPathBuilderInner::ChosenExit(e) = &self.inner { - Some(e) - } else { - None - }; - let path_is_fully_random = chosen_exit.is_none(); - - // TODO-SPEC: Because of limitations in guard selection, we have to - // pick the guard before the exit, which is not what our spec says. - let (guard, mon, usable) = match guards { - Some(guardmgr) => { - // TODO: Extract this section into its own function, and see - // what it can share with tor_relay_selection. - let mut b = tor_guardmgr::GuardUsageBuilder::default(); - b.kind(tor_guardmgr::GuardUsageKind::Data); - if let Some(exit_relay) = chosen_exit { - // TODO(nickm): Our way of building a family here is - // somewhat questionable. We're only adding the ed25519 - // identities of the exit relay and its family to the - // RelayId set. That's fine for now, since we will only use - // relays at this point if they have a known Ed25519 - // identity. But if in the future the ed25519 identity - // becomes optional, this will need to change. - let mut family = RelayIdSet::new(); - family.insert(*exit_relay.id()); - // TODO(nickm): See "limitations" note on `known_family_members`. - family.extend(netdir.known_family_members(exit_relay).map(|r| *r.id())); - b.restrictions() - .push(tor_guardmgr::GuardRestriction::AvoidAllIds(family)); - } - if let Some(avoid_target) = &self.compatible_with { - let mut family = RelayIdSet::new(); - family.extend(avoid_target.identities().map(|id| id.to_owned())); - if let Some(avoid_relay) = netdir.by_ids(avoid_target) { - family.extend(netdir.known_family_members(&avoid_relay).map(|r| *r.id())); - } - b.restrictions() - .push(tor_guardmgr::GuardRestriction::AvoidAllIds(family)); - } - let guard_usage = b.build().expect("Failed while building guard usage!"); - let (guard, mut mon, usable) = guardmgr.select_guard(guard_usage)?; - let guard = if let Some(ct) = guard.as_circ_target() { - // This is a bridge; we will not look for it in the network directory. - MaybeOwnedRelay::from(ct.clone()) - } else { - // Look this up in the network directory: we expect to find a relay. - guard - .get_relay(netdir) - .ok_or_else(|| { - internal!( - "Somehow the guardmgr gave us an unlisted guard {:?}!", - guard - ) - })? - .into() - }; - if !path_is_fully_random { - // We were given a specific exit relay to use, and - // the choice of exit relay might be forced by - // something outside of our control. - // - // Therefore, we must not blame the guard for any failure - // to complete the circuit. - mon.ignore_indeterminate_status(); - } - (guard, Some(mon), Some(usable)) - } - None => { - let rs_cfg = config.relay_selection_config(); - let exclusion = match chosen_exit { - Some(r) => { - RelayExclusion::exclude_relays_in_same_family(&rs_cfg, vec![r.clone()]) - } - None => RelayExclusion::no_relays_excluded(), - }; - let selector = RelaySelector::new(RelayUsage::new_guard(), exclusion); - let (relay, info) = selector.select_relay(rng, netdir); - let relay = relay.ok_or_else(|| Error::NoRelay { - path_kind: self.path_kind(), - role: "entry", - problem: info.to_string(), - })?; - - (MaybeOwnedRelay::from(relay), None, None) - } - }; - - let guard_exclusion = match &guard { - MaybeOwnedRelay::Relay(r) => RelayExclusion::exclude_relays_in_same_family( - &config.relay_selection_config(), - vec![r.clone()], - ), - MaybeOwnedRelay::Owned(ct) => RelayExclusion::exclude_channel_target_family( - &config.relay_selection_config(), - ct.as_ref(), - netdir, - ), - }; - - let (exit, middle_usage) = self.pick_exit(rng, netdir, guard_exclusion.clone(), &rs_cfg)?; - - let mut family_exclusion = - RelayExclusion::exclude_relays_in_same_family(&rs_cfg, vec![exit.clone()]); - family_exclusion.extend(&guard_exclusion); - - let selector = RelaySelector::new(middle_usage, family_exclusion); - let (middle, info) = selector.select_relay(rng, netdir); - let middle = middle.ok_or_else(|| Error::NoRelay { - path_kind: self.path_kind(), - role: "middle relay", - problem: info.to_string(), - })?; - - Ok(( - TorPath::new_multihop_from_maybe_owned(vec![ - guard, - MaybeOwnedRelay::from(middle), - MaybeOwnedRelay::from(exit), - ]), - mon, - usable, - )) - } - - /// Return a short description of the path we're trying to build, - /// for error reporting purposes. fn path_kind(&self) -> &'static str { use ExitPathBuilderInner::*; match &self.inner { @@ -371,7 +215,6 @@ impl<'a> ExitPathBuilder<'a> { #[cfg(feature = "geoip")] ExitInCountry { .. } => "country-specific exit circuit", AnyExit { .. } => "testing circuit", - AnyRelayForOnionService => "onion-service circuit", ChosenExit(_) => "circuit to a specific exit", } } @@ -393,7 +236,9 @@ mod test { #![allow(clippy::needless_pass_by_value)] //! <!-- @@ end test lint list maintained by maint/add_warning @@ --> use super::*; - use crate::path::{assert_same_path_when_owned, MaybeOwnedRelay, OwnedPath, TorPathInner}; + use crate::path::{ + assert_same_path_when_owned, MaybeOwnedRelay, OwnedPath, TorPath, TorPathInner, + }; use crate::test::OptDummyGuardMgr; use std::collections::HashSet; use tor_basic_utils::test_rng::testing_rng; diff --git a/crates/tor-circmgr/src/path/hspath.rs b/crates/tor-circmgr/src/path/hspath.rs new file mode 100644 index 000000000..4fab2eb70 --- /dev/null +++ b/crates/tor-circmgr/src/path/hspath.rs @@ -0,0 +1,124 @@ +//! Code for building paths for HS circuits. + +use rand::Rng; +use tor_linkspec::OwnedChanTarget; +use tor_netdir::{NetDir, Relay}; +use tor_relay_selection::{RelayExclusion, RelaySelectionConfig, RelaySelector, RelayUsage}; + +use crate::{Error, Result}; + +use super::AnonymousPathBuilder; + +use { + crate::path::TorPath, + crate::{DirInfo, PathConfig}, + std::time::SystemTime, + tor_guardmgr::{GuardMgr, GuardMonitor, GuardUsable}, + tor_rtcompat::Runtime, +}; + +/// A path builder for hidden service circuits. +/// +/// This builder is used for creating hidden service stub circuits, +/// which are three-hop circuits that have not yet been extended to a target. +/// +/// Stub circuits eventually become introduction, rendezvous, and HsDir circuits. +/// For all circuit types except client rendezvous, the stubs must first be +/// extended by an extra hop: +/// +/// ```text +/// Client hsdir: STUB+ -> HsDir +/// Client intro: STUB+ -> Ipt +/// Client rend: STUB +/// Service hsdir: STUB -> HsDir +/// Service intro: STUB -> Ipt +/// Service rend: STUB+ -> Rpt +/// ``` +/// +/// While we don't currently distinguish between regular stub circuits (STUB), +/// and extended stub circuits (STUB+), the two will be handled differently +/// once we add support for vanguards. +pub struct HsPathBuilder { + /// If present, a "target" that every chosen relay must be able to share a circuit with with. + compatible_with: Option<OwnedChanTarget>, +} + +impl HsPathBuilder { + /// Create a new builder that will try to build a three-hop non-exit path + /// for use with the onion services protocols + /// that is compatible with being extended to an optional given relay. + /// + /// (The provided relay is _not_ included in the built path: we only ensure + /// that the path we build does not have any features that would stop us + /// extending it to that relay as a fourth hop.) + pub(crate) fn new(compatible_with: Option<OwnedChanTarget>) -> Self { + Self { compatible_with } + } + + /// Try to create and return a path for a hidden service circuit stub. + #[cfg(not(feature = "vanguards"))] + pub fn pick_path<'a, R: Rng, RT: Runtime>( + &self, + rng: &mut R, + netdir: DirInfo<'a>, + guards: Option<&GuardMgr<RT>>, + config: &PathConfig, + now: SystemTime, + ) -> Result<(TorPath<'a>, Option<GuardMonitor>, Option<GuardUsable>)> { + use super::pick_path; + + pick_path(self, rng, netdir, guards, config, now) + } + + /// Try to create and return a path for a hidden service circuit stub. + #[cfg(feature = "vanguards")] + pub fn pick_path<'a, R: Rng, RT: Runtime>( + &self, + _rng: &mut R, + _netdir: DirInfo<'a>, + _guards: Option<&GuardMgr<RT>>, + _config: &PathConfig, + _now: SystemTime, + ) -> Result<(TorPath<'a>, Option<GuardMonitor>, Option<GuardUsable>)> { + // TODO HS-VANGUARDS (#1279): this will likely share some logic with + // AnonymousPathBuilder::pick_path, so we might want to split + // AnonymousPathBuilder::pick_path into multiple smaller functions + // that we can use here + todo!() + } +} + +impl<'a> AnonymousPathBuilder<'a> for HsPathBuilder { + fn chosen_exit(&self) -> Option<&Relay<'_>> { + None + } + + fn compatible_with(&self) -> Option<&OwnedChanTarget> { + self.compatible_with.as_ref() + } + + fn path_kind(&self) -> &'static str { + "onion-service circuit" + } + + fn pick_exit<'s, R: Rng>( + &'s self, + rng: &mut R, + netdir: &'a NetDir, + guard_exclusion: RelayExclusion<'a>, + _rs_cfg: &RelaySelectionConfig<'_>, + ) -> Result<(Relay<'a>, RelayUsage)> { + // TODO: This usage is a bit convoluted, and some onion-service- + // related circuits don't need this much stability. + let usage = RelayUsage::middle_relay(Some(&RelayUsage::new_intro_point())); + let selector = RelaySelector::new(usage, guard_exclusion); + + let (relay, info) = selector.select_relay(rng, netdir); + let relay = relay.ok_or_else(|| Error::NoRelay { + path_kind: self.path_kind(), + role: "final hop", + problem: info.to_string(), + })?; + Ok((relay, RelayUsage::middle_relay(Some(selector.usage())))) + } +} diff --git a/crates/tor-circmgr/src/usage.rs b/crates/tor-circmgr/src/usage.rs index 7c40f037c..d30402030 100644 --- a/crates/tor-circmgr/src/usage.rs +++ b/crates/tor-circmgr/src/usage.rs @@ -8,6 +8,8 @@ use tracing::trace; #[cfg(not(feature = "geoip"))] use void::Void; +#[cfg(feature = "hs-common")] +use crate::path::hspath::HsPathBuilder; use crate::path::{dirpath::DirPathBuilder, exitpath::ExitPathBuilder, TorPath}; use tor_chanmgr::ChannelUsage; #[cfg(feature = "geoip")] @@ -333,12 +335,8 @@ impl TargetCircUsage { TargetCircUsage::HsCircBase { compatible_with_target, } => { - let (path, mon, usable) = - ExitPathBuilder::for_onion_service(compatible_with_target.clone()) - // TODO: We don't actually require stability if this is a - // HsDir circuit: but at this point, we can't tell. - .require_stability(true) - .pick_path(rng, netdir, guards, config, now)?; + let (path, mon, usable) = HsPathBuilder::new(compatible_with_target.clone()) + .pick_path(rng, netdir, guards, config, now)?; let usage = SupportedCircUsage::HsOnly; Ok((path, usage, mon, usable)) } diff --git a/tests/shadow/README.md b/tests/shadow/README.md index 533d431a9..e7b78c308 100644 --- a/tests/shadow/README.md +++ b/tests/shadow/README.md @@ -37,7 +37,7 @@ locations where [`shadow.yaml`](./shadow.yaml) expects to find them. job `rust-latest` with the invocation: ```shell - $ cargo build --locked --verbose --target x86_64-unknown-linux-gnu + $ cargo build --locked --verbose --target x86_64-unknown-linux-gnu -p arti ``` Once those are installed, you can invoke the [`run.sh`](./run.sh) script from |