proto: Implement Circuit::extend_virtual.

There are a few new TODO hs comments, though, and an XXXX I'll need
to fix up in the next commit.

Implements #726.
This commit is contained in:
Nick Mathewson 2023-05-18 09:47:22 -04:00
parent b9a848a7ac
commit 663f25d44c
2 changed files with 59 additions and 2 deletions

View File

@ -402,17 +402,32 @@ impl ClientCirc {
// TODO hs: let's try to enforce the "you can't extend a circuit again once
// it has been extended this way" property. We could do that with internal
// state, or some kind of a type state pattern.
//
// TODO hs: Possibly we should take a description of the hop.
//
// TODO hs: possibly we should take a set of Protovers, and not just `Params`.
#[cfg(feature = "hs-common")]
#[allow(clippy::missing_panics_doc, unused_variables)]
pub async fn extend_virtual(
&self,
protocol: handshake::RelayProtocol,
role: handshake::HandshakeRole,
seed: impl handshake::KeyGenerator,
params: CircParameters,
) -> Result<()> {
let (outbound, inbound) = protocol.construct_layers(role, seed)?;
todo!() // TODO hs implement
let (tx, rx) = oneshot::channel();
let message = CtrlMsg::ExtendVirtual {
cell_crypto: (outbound, inbound),
params,
done: tx,
};
self.control
.unbounded_send(message)
.map_err(|_| Error::CircuitClosed)?;
rx.await.map_err(|_| Error::CircuitClosed)?
}
/// Helper, used to begin a stream.

View File

@ -122,6 +122,24 @@ pub(super) enum CtrlMsg {
/// Oneshot channel to notify on completion.
done: ReactorResultChannel<()>,
},
/// Extend the circuit by one hop, in response to an out-of-band handshake.
///
/// (This is used for onion services, where the negotiation takes place in
/// INTRODUCE and RENDEZVOUS messages.)
#[cfg(feature = "hs-common")]
ExtendVirtual {
/// The cryptographic algorithms and keys to use when communicating with
/// the newly added hop.
#[educe(Debug(ignore))]
cell_crypto: (
Box<dyn OutboundClientLayer + Send>,
Box<dyn InboundClientLayer + Send>,
),
/// A set of parameters used to configure this hop.
params: CircParameters,
/// Oneshot channel to notify on completion.
done: ReactorResultChannel<()>,
},
/// Begin a stream with the provided hop in this circuit.
///
/// Allocates a stream ID, and sends the provided message to that hop.
@ -1227,6 +1245,30 @@ impl Reactor {
)?;
self.set_meta_handler(Box::new(extender))?;
}
#[cfg(feature = "hs-common")]
#[allow(unreachable_code)]
CtrlMsg::ExtendVirtual {
cell_crypto,
params,
done,
} => {
let (outbound, inbound) = cell_crypto;
// XXXX TODO HS: This is not correct! we should instead have an
// onion service variant we can use for the peer ID of a hop.
let peer_id = OwnedChanTarget::builder().build().expect("whoopsie");
// TODO HS: This is not really correct! We probably should be
// looking at the sendme_auth_accept_min_version parameter. See
// comments in RequireSendmeAuth::from_protocols.
//
// "Yes" should be safe, however, since Tor <=0.3.5 is
// emphatically unsupported.
let require_sendme_auth = RequireSendmeAuth::Yes;
self.add_hop(peer_id, require_sendme_auth, outbound, inbound, &params);
let _ = done.send(Ok(()));
}
CtrlMsg::BeginStream {
hop_num,
message,