Commit 1e75ff59 authored by gabi-250's avatar gabi-250 🕸️
Browse files

Merge branch 'tor-circmgr-0.18.1' into 'tor-circmgr-0.18.1'

TROVE-2024-003: Prepare release

See merge request tpo/core/arti!2154
parents f7aeca74 70744781
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -3,6 +3,46 @@
This file describes changes in Arti through the current release.  Once Arti
is more mature, we may switch to using a separate changelog for each crate.

# Arti 1.2.3 — 15 May 2024

Arti 1.2.3 fixes a high-severity issue affecting onion services and clients
connecting to onion services with 'lite' vanguards (the default) enabled:
when building anonymizing circuits to or from an onion service
the circuit manager code would build the circuits with one hop too few.
This makes users of this code more vulnerable to some kinds of traffic analysis
when they run or visit onion services.

This release also fixes a medium-severity issue affecting 'full' vanguards.
With 'full' vanguards enabled, client HsDir circuits, client introduction
circuits and service rendezvous-circuits are extended with an extra hop to
minimize the linkability of the guard nodes.
In some circumstances, the circuit manager would build circuits with one
hop too few, making it easier for an adversary to discover the L2 and L3
guards of the affected clients and services.

In Arti 1.2.1 and earlier, vanguards were still an experimental feature, or
absent, so those versions are classified as "not affected", even though
downgrading does not fix the security problem.

### Major bugfixes

- Fix a high-severity issue affecting onion service circuits using 'lite'
  vanguards. Previously, with 'lite' vanguards enabled, any circuit to or from
  an onion service was one hop too short, making clients and services vulnerable
  to certain types of traffic analysis. This is also tracked as
  [TROVE-2024-003]. ([#1409])

- Fix a medium-severity issue affecting onion service circuits using 'full'
  vanguards. Previously, with 'full' vanguards enabled, *some* circuits to or from
  an onion service were one hop too short, making linkability attacks more
  likely to succeed.
  [TROVE-2024-004]. ([#1400])

[#1400]: https://gitlab.torproject.org/tpo/core/arti/-/issues/1400
[#1409]: https://gitlab.torproject.org/tpo/core/arti/-/issues/1409
[TROVE-2024-003]: https://gitlab.torproject.org/tpo/core/team/-/wikis/NetworkTeam/TROVE
[TROVE-2024-004]: https://gitlab.torproject.org/tpo/core/team/-/wikis/NetworkTeam/TROVE

# Arti 1.2.2 — 30 April 2024

Arti 1.2.2 continues improvements on previous releases,
+2 −2
Original line number Diff line number Diff line
@@ -195,7 +195,7 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"

[[package]]
name = "arti"
version = "1.2.2"
version = "1.2.3"
dependencies = [
 "anyhow",
 "arti-client",
@@ -5046,7 +5046,7 @@ dependencies = [

[[package]]
name = "tor-circmgr"
version = "0.18.0"
version = "0.18.1"
dependencies = [
 "amplify",
 "async-trait",
+1 −1
Original line number Diff line number Diff line
[package]
name = "arti"
version = "1.2.2"
version = "1.2.3"
authors = ["The Tor Project, Inc.", "Nick Mathewson <nickm@torproject.org>"]
edition = "2021"
rust-version = "1.70"
+1 −1
Original line number Diff line number Diff line
[package]
name = "tor-circmgr"
version = "0.18.0"
version = "0.18.1"
authors = ["The Tor Project, Inc.", "Nick Mathewson <nickm@torproject.org>"]
edition = "2021"
rust-version = "1.70"
+57 −10
Original line number Diff line number Diff line
@@ -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)
            }
Loading