Skip to content
Snippets Groups Projects
Commit 764930b9 authored by Nick Mathewson's avatar Nick Mathewson :game_die:
Browse files

tor-proto: Remember peer information in circuit and channel

Each channel now remembers an OwnedChanTarget.

Each circuit now remembers a vector of OwnedChanTarget to represent
the path that it was constructed for.

Part of #415.
parent 567995a7
No related branches found
No related tags found
No related merge requests found
......@@ -71,7 +71,7 @@ use crate::{Error, Result};
use std::pin::Pin;
use tor_cell::chancell::{msg, ChanCell, CircId};
use tor_error::internal;
use tor_linkspec::ChanTarget;
use tor_linkspec::{ChanTarget, OwnedChanTarget};
use tor_llcrypto::pk::ed25519::Ed25519Identity;
use tor_llcrypto::pk::rsa::RsaIdentity;
......@@ -126,10 +126,8 @@ pub struct Channel {
pub(crate) struct ChannelDetails {
/// A unique identifier for this channel.
unique_id: UniqId,
/// Validated Ed25519 identity for this peer.
ed25519_id: Ed25519Identity,
/// Validated RSA identity for this peer.
rsa_id: RsaIdentity,
/// Validated identity and address information for this peer.
peer_id: OwnedChanTarget,
/// If true, this channel is closing.
closed: AtomicBool,
/// Since when the channel became unused.
......@@ -240,8 +238,7 @@ impl Channel {
sink: BoxedChannelSink,
stream: BoxedChannelStream,
unique_id: UniqId,
ed25519_id: Ed25519Identity,
rsa_id: RsaIdentity,
peer_id: OwnedChanTarget,
) -> (Self, reactor::Reactor) {
use circmap::{CircIdRange, CircMap};
let circmap = CircMap::new(CircIdRange::High);
......@@ -254,8 +251,7 @@ impl Channel {
let details = ChannelDetails {
unique_id,
ed25519_id,
rsa_id,
peer_id,
closed,
unused_since,
};
......@@ -288,12 +284,18 @@ impl Channel {
/// Return the Ed25519 identity for the peer of this channel.
pub fn peer_ed25519_id(&self) -> &Ed25519Identity {
&self.details.ed25519_id
self.details.peer_id.ed_identity()
}
/// Return the (legacy) RSA identity for the peer of this channel.
pub fn peer_rsa_id(&self) -> &RsaIdentity {
&self.details.rsa_id
self.details.peer_id.rsa_identity()
}
/// Return an OwnedChanTarget representing the actual handshake used to
/// create this channel.
pub fn target(&self) -> &OwnedChanTarget {
&self.details.peer_id
}
/// Return an error if this channel is somehow mismatched with the
......@@ -452,11 +454,11 @@ pub(crate) mod test {
fn fake_channel_details() -> Arc<ChannelDetails> {
let unique_id = UniqId::new();
let unused_since = OptTimestamp::new();
let peer_id = OwnedChanTarget::new(vec![], [6_u8; 32].into(), [10_u8; 20].into());
Arc::new(ChannelDetails {
unique_id,
ed25519_id: [6_u8; 32].into(),
rsa_id: [10_u8; 20].into(),
peer_id,
closed: AtomicBool::new(false),
unused_since,
})
......
......@@ -16,7 +16,7 @@ use std::net::SocketAddr;
use std::sync::Arc;
use tor_bytes::Reader;
use tor_linkspec::ChanTarget;
use tor_linkspec::{ChanTarget, OwnedChanTarget};
use tor_llcrypto as ll;
use tor_llcrypto::pk::ed25519::Ed25519Identity;
use tor_llcrypto::pk::rsa::RsaIdentity;
......@@ -453,13 +453,18 @@ impl<T: AsyncRead + AsyncWrite + Send + Unpin + 'static> VerifiedChannel<T> {
let (tls_sink, tls_stream) = self.tls.split();
let peer_id = OwnedChanTarget::new(
self.target_addr.into_iter().collect(),
self.ed25519_id,
self.rsa_id,
);
Ok(super::Channel::new(
self.link_protocol,
Box::new(tls_sink),
Box::new(tls_stream),
self.unique_id,
self.ed25519_id,
self.rsa_id,
peer_id,
))
}
}
......
......@@ -417,6 +417,7 @@ pub(crate) mod test {
use futures::sink::SinkExt;
use futures::stream::StreamExt;
use futures::task::SpawnExt;
use tor_linkspec::OwnedChanTarget;
type CodecResult = std::result::Result<ChanCell, CodecError>;
......@@ -430,8 +431,7 @@ pub(crate) mod test {
let (send1, recv1) = mpsc::channel(32);
let (send2, recv2) = mpsc::channel(32);
let unique_id = UniqId::new();
let ed_id = [6; 32].into();
let rsa_id = [10; 20].into();
let dummy_target = OwnedChanTarget::new(vec![], [6; 32].into(), [10; 20].into());
let send1 = send1.sink_map_err(|e| {
trace!("got sink error: {}", e);
CodecError::Cell(tor_cell::Error::ChanProto("dummy message".into()))
......@@ -441,8 +441,7 @@ pub(crate) mod test {
Box::new(send1),
Box::new(recv2),
unique_id,
ed_id,
rsa_id,
dummy_target,
);
(chan, reactor, recv1, send2)
}
......
......@@ -61,13 +61,14 @@ use tor_cell::{
relaycell::msg::{Begin, RelayMsg, Resolve, Resolved, ResolvedVal},
};
use tor_error::{bad_api_usage, internal};
use tor_linkspec::{CircTarget, LinkSpec};
use tor_error::{bad_api_usage, internal, into_internal};
use tor_linkspec::{CircTarget, LinkSpec, OwnedChanTarget};
use futures::channel::{mpsc, oneshot};
use crate::circuit::sendme::StreamRecvWindow;
use futures::SinkExt;
use std::convert::TryFrom;
use std::net::IpAddr;
use std::sync::Arc;
use tor_cell::relaycell::StreamId;
......@@ -211,8 +212,10 @@ impl ClientCirc {
let (tx, rx) = oneshot::channel();
let peer_id = OwnedChanTarget::from_chan_target(target);
self.control
.unbounded_send(CtrlMsg::ExtendNtor {
peer_id,
public_key: key,
linkspecs,
require_sendme_auth,
......@@ -243,7 +246,9 @@ impl ClientCirc {
"Can't begin a stream at the 0th hop"
)));
}
let hop_num: HopNum = (num_hops - 1).into();
let hop_num: HopNum = u8::try_from(num_hops - 1)
.map_err(into_internal!("Couldn't convert path length to u8"))?
.into();
let (sender, receiver) = mpsc::channel(STREAM_READER_BUFFER);
let (tx, rx) = oneshot::channel();
let (msg_tx, msg_rx) = mpsc::channel(CIRCUIT_BUFFER_SIZE);
......@@ -405,7 +410,7 @@ impl ClientCirc {
}
#[cfg(test)]
pub fn n_hops(&self) -> u8 {
pub fn n_hops(&self) -> usize {
self.path.n_hops()
}
}
......
//! Tracking for the path of a client circuit.
use std::sync::atomic::{AtomicU8, Ordering};
use std::sync::Mutex;
use tor_linkspec::OwnedChanTarget;
/// Helper struct that shares information
#[derive(Debug, Default)]
pub(super) struct Path {
/// Number of hops on this circuit.
/// Information about the relays on this circuit.
///
/// This value is incremented after the circuit successfully completes extending to a new hop.
n_hops: AtomicU8,
/// We only store ChanTarget information here, because it doesn't matter
/// which ntor key we actually used with each hop.
hops: Mutex<Vec<OwnedChanTarget>>,
}
impl Path {
/// Return the number of hops in this path
pub(super) fn n_hops(&self) -> u8 {
self.n_hops.load(Ordering::SeqCst)
pub(super) fn n_hops(&self) -> usize {
self.hops.lock().expect("poisoned lock").len()
}
/// Add 1 to the number of hops in this path.
pub(super) fn inc_hops(&self) {
self.n_hops.fetch_add(1, Ordering::SeqCst);
/// Add a hop to this this path.
pub(super) fn push_hop(&self, target: OwnedChanTarget) {
self.hops.lock().expect("poisoned lock").push(target);
}
}
......@@ -36,7 +36,7 @@ use crate::crypto::handshake::ntor::{NtorClient, NtorPublicKey};
use crate::crypto::handshake::{ClientHandshake, KeyGenerator};
use tor_cell::chancell;
use tor_cell::chancell::{ChanCell, CircId};
use tor_linkspec::LinkSpec;
use tor_linkspec::{LinkSpec, OwnedChanTarget};
use tor_llcrypto::pk;
use tracing::{debug, trace, warn};
......@@ -88,6 +88,10 @@ pub(super) enum CtrlMsg {
},
/// Extend a circuit by one hop, using the ntor handshake.
ExtendNtor {
/// The peer that we're extending to.
///
/// Used to extend our record of the circuit's path.
peer_id: OwnedChanTarget,
/// The handshake type to use for this hop.
public_key: NtorPublicKey,
/// Information about how to connect to the relay we're extending to.
......@@ -267,6 +271,10 @@ struct CircuitExtender<H, L, FWD, REV>
where
H: ClientHandshake,
{
/// The peer that we're extending to.
///
/// Used to extend our record of the circuit's path.
peer_id: OwnedChanTarget,
/// Handshake state.
state: Option<H::StateType>,
/// Whether the hop supports authenticated SENDME cells.
......@@ -302,8 +310,10 @@ where
/// goes along with the handshake, and the `linkspecs` are the
/// link specifiers to include in the EXTEND cell to tell the
/// current last hop which relay to connect to.
#[allow(clippy::too_many_arguments)]
fn begin(
cx: &mut Context<'_>,
peer_id: OwnedChanTarget,
handshake_id: u16,
key: &H::KeyType,
linkspecs: Vec<LinkSpec>,
......@@ -340,6 +350,7 @@ where
// ... and now we wait for a response.
Ok(Self {
peer_id,
state: Some(state),
require_sendme_auth,
params,
......@@ -405,6 +416,7 @@ where
// If we get here, it succeeded. Add a new hop to the circuit.
let (layer_fwd, layer_back) = layer.split();
reactor.add_hop(
self.peer_id.clone(),
self.require_sendme_auth,
Box::new(layer_fwd),
Box::new(layer_back),
......@@ -722,7 +734,10 @@ impl Reactor {
debug!("{}: Handshake complete; circuit created.", self.unique_id);
let (layer_fwd, layer_back) = layer.split();
let peer_id = self.channel.target().clone();
self.add_hop(
peer_id,
require_sendme_auth,
Box::new(layer_fwd),
Box::new(layer_back),
......@@ -799,6 +814,7 @@ impl Reactor {
/// Add a hop to the end of this circuit.
fn add_hop(
&mut self,
peer_id: OwnedChanTarget,
require_sendme_auth: RequireSendmeAuth,
fwd: Box<dyn OutboundClientLayer + 'static + Send>,
rev: Box<dyn InboundClientLayer + 'static + Send>,
......@@ -811,7 +827,7 @@ impl Reactor {
self.hops.push(hop);
self.crypto_in.add_layer(rev);
self.crypto_out.add_layer(fwd);
self.path.inc_hops();
self.path.push_hop(peer_id);
}
/// Handle a RELAY cell on this circuit with stream ID 0.
......@@ -1055,6 +1071,7 @@ impl Reactor {
// This is handled earlier, since it requires generating a ReactorError.
CtrlMsg::Shutdown => panic!("got a CtrlMsg::Shutdown in handle_control"),
CtrlMsg::ExtendNtor {
peer_id,
public_key,
linkspecs,
require_sendme_auth,
......@@ -1063,6 +1080,7 @@ impl Reactor {
} => {
match CircuitExtender::<NtorClient, Tor1RelayCrypto, _, _>::begin(
cx,
peer_id,
0x02,
&public_key,
linkspecs,
......@@ -1110,9 +1128,10 @@ impl Reactor {
RequireSendmeAuth::No
};
let dummy_peer_id = OwnedChanTarget::new(vec![], [4; 32].into(), [5; 20].into());
let fwd = Box::new(DummyCrypto::new(fwd_lasthop));
let rev = Box::new(DummyCrypto::new(rev_lasthop));
self.add_hop(require_sendme_auth, fwd, rev, &params);
self.add_hop(dummy_peer_id, require_sendme_auth, fwd, rev, &params);
let _ = done.send(Ok(()));
}
#[cfg(test)]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment