[libp2p-noise] Disable sending of legacy handshake payloads (by default). (#1669)

* [libp2p-noise] Disable sending of legacy handshake payloads.

* Update build_development_transport() to use libp2p-noise.

* Update feature flags.

* Replace feature flag by config options.

* Cleanup

* Cleanup

* Cleanup
This commit is contained in:
Roman Borschel
2020-08-03 14:52:34 +02:00
committed by GitHub
parent d8ad7bddf5
commit e0e5dfbe50
7 changed files with 133 additions and 25 deletions

View File

@@ -1,3 +1,21 @@
# 0.22.0 [2020-??-??]
**NOTE**: For a smooth upgrade path from `0.20` to `> 0.21`
on an existing deployment, this version must not be skipped
or the provided `LegacyConfig` used!
- Stop sending length-prefixed protobuf frames in handshake
payloads by default. See [issue 1631](https://github.com/libp2p/rust-libp2p/issues/1631).
The new `LegacyConfig` is provided to optionally
configure sending the legacy handshake. Note: This release
always supports receiving legacy handshake payloads. A future
release will also move receiving legacy handshake payloads
into a `LegacyConfig` option. However, all legacy configuration
options will eventually be removed, so this is primarily to allow
delaying the handshake upgrade or keeping compatibility with a network
whose peers are slow to upgrade, without having to freeze the
version of `libp2p-noise` altogether in these projects.
# 0.21.0 [2020-07-17]
**NOTE**: For a smooth upgrade path from `0.20` to `> 0.21`

View File

@@ -1,7 +1,7 @@
[package]
name = "libp2p-noise"
description = "Cryptographic handshake protocol using the noise framework."
version = "0.21.0"
version = "0.22.0"
authors = ["Parity Technologies <admin@parity.io>"]
license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p"

View File

@@ -25,6 +25,7 @@ mod payload_proto {
}
use bytes::Bytes;
use crate::LegacyConfig;
use crate::error::NoiseError;
use crate::protocol::{Protocol, PublicKey, KeypairIdentity};
use crate::io::{NoiseOutput, framed::NoiseFramed};
@@ -125,14 +126,15 @@ pub fn rt1_initiator<T, C>(
io: T,
session: Result<snow::HandshakeState, NoiseError>,
identity: KeypairIdentity,
identity_x: IdentityExchange
identity_x: IdentityExchange,
legacy: LegacyConfig,
) -> Handshake<T, C>
where
T: AsyncWrite + AsyncRead + Send + Unpin + 'static,
C: Protocol<C> + AsRef<[u8]>
{
Handshake(Box::pin(async move {
let mut state = State::new(io, session, identity, identity_x)?;
let mut state = State::new(io, session, identity, identity_x, legacy)?;
send_identity(&mut state).await?;
recv_identity(&mut state).await?;
state.finish()
@@ -160,13 +162,14 @@ pub fn rt1_responder<T, C>(
session: Result<snow::HandshakeState, NoiseError>,
identity: KeypairIdentity,
identity_x: IdentityExchange,
legacy: LegacyConfig,
) -> Handshake<T, C>
where
T: AsyncWrite + AsyncRead + Send + Unpin + 'static,
C: Protocol<C> + AsRef<[u8]>
{
Handshake(Box::pin(async move {
let mut state = State::new(io, session, identity, identity_x)?;
let mut state = State::new(io, session, identity, identity_x, legacy)?;
recv_identity(&mut state).await?;
send_identity(&mut state).await?;
state.finish()
@@ -195,14 +198,15 @@ pub fn rt15_initiator<T, C>(
io: T,
session: Result<snow::HandshakeState, NoiseError>,
identity: KeypairIdentity,
identity_x: IdentityExchange
identity_x: IdentityExchange,
legacy: LegacyConfig,
) -> Handshake<T, C>
where
T: AsyncWrite + AsyncRead + Unpin + Send + 'static,
C: Protocol<C> + AsRef<[u8]>
{
Handshake(Box::pin(async move {
let mut state = State::new(io, session, identity, identity_x)?;
let mut state = State::new(io, session, identity, identity_x, legacy)?;
send_empty(&mut state).await?;
recv_identity(&mut state).await?;
send_identity(&mut state).await?;
@@ -232,14 +236,15 @@ pub fn rt15_responder<T, C>(
io: T,
session: Result<snow::HandshakeState, NoiseError>,
identity: KeypairIdentity,
identity_x: IdentityExchange
identity_x: IdentityExchange,
legacy: LegacyConfig,
) -> Handshake<T, C>
where
T: AsyncWrite + AsyncRead + Unpin + Send + 'static,
C: Protocol<C> + AsRef<[u8]>
{
Handshake(Box::pin(async move {
let mut state = State::new(io, session, identity, identity_x)?;
let mut state = State::new(io, session, identity, identity_x, legacy)?;
recv_empty(&mut state).await?;
send_identity(&mut state).await?;
recv_identity(&mut state).await?;
@@ -263,6 +268,8 @@ struct State<T> {
id_remote_pubkey: Option<identity::PublicKey>,
/// Whether to send the public identity key of the local node to the remote.
send_identity: bool,
/// Legacy configuration parameters.
legacy: LegacyConfig,
}
impl<T> State<T> {
@@ -275,7 +282,8 @@ impl<T> State<T> {
io: T,
session: Result<snow::HandshakeState, NoiseError>,
identity: KeypairIdentity,
identity_x: IdentityExchange
identity_x: IdentityExchange,
legacy: LegacyConfig,
) -> Result<Self, NoiseError> {
let (id_remote_pubkey, send_identity) = match identity_x {
IdentityExchange::Mutual => (None, true),
@@ -289,7 +297,8 @@ impl<T> State<T> {
io: NoiseFramed::new(io, s),
dh_remote_pubkey_sig: None,
id_remote_pubkey,
send_identity
send_identity,
legacy,
}
)
}
@@ -424,17 +433,26 @@ where
T: AsyncWrite + Unpin,
{
let mut pb = payload_proto::NoiseHandshakePayload::default();
if state.send_identity {
pb.identity_key = state.identity.public.clone().into_protobuf_encoding()
}
if let Some(ref sig) = state.identity.signature {
pb.identity_sig = sig.clone()
}
// NOTE: We temporarily need to continue sending the (legacy) length prefix
// for a short while to permit migration.
let mut msg = Vec::with_capacity(pb.encoded_len() + 2);
msg.extend_from_slice(&(pb.encoded_len() as u16).to_be_bytes());
let mut msg =
if state.legacy.send_legacy_handshake {
let mut msg = Vec::with_capacity(2 + pb.encoded_len());
msg.extend_from_slice(&(pb.encoded_len() as u16).to_be_bytes());
msg
} else {
Vec::with_capacity(pb.encoded_len())
};
pb.encode(&mut msg).expect("Vec<u8> provides capacity as needed");
state.io.send(&msg).await?;
Ok(())
}

View File

@@ -76,6 +76,7 @@ use zeroize::Zeroize;
pub struct NoiseConfig<P, C: Zeroize, R = ()> {
dh_keys: AuthenticKeypair<C>,
params: ProtocolParams,
legacy: LegacyConfig,
remote: R,
_marker: std::marker::PhantomData<P>
}
@@ -86,6 +87,12 @@ impl<H, C: Zeroize, R> NoiseConfig<H, C, R> {
pub fn into_authenticated(self) -> NoiseAuthenticated<H, C, R> {
NoiseAuthenticated { config: self }
}
/// Sets the legacy configuration options to use, if any.
pub fn set_legacy_config(&mut self, cfg: LegacyConfig) -> &mut Self {
self.legacy = cfg;
self
}
}
impl<C> NoiseConfig<IX, C>
@@ -97,6 +104,7 @@ where
NoiseConfig {
dh_keys,
params: C::params_ix(),
legacy: LegacyConfig::default(),
remote: (),
_marker: std::marker::PhantomData
}
@@ -112,6 +120,7 @@ where
NoiseConfig {
dh_keys,
params: C::params_xx(),
legacy: LegacyConfig::default(),
remote: (),
_marker: std::marker::PhantomData
}
@@ -130,6 +139,7 @@ where
NoiseConfig {
dh_keys,
params: C::params_ik(),
legacy: LegacyConfig::default(),
remote: (),
_marker: std::marker::PhantomData
}
@@ -152,6 +162,7 @@ where
NoiseConfig {
dh_keys,
params: C::params_ik(),
legacy: LegacyConfig::default(),
remote: (remote_dh, remote_id),
_marker: std::marker::PhantomData
}
@@ -177,7 +188,8 @@ where
.map_err(NoiseError::from);
handshake::rt1_responder(socket, session,
self.dh_keys.into_identity(),
IdentityExchange::Mutual)
IdentityExchange::Mutual,
self.legacy)
}
}
@@ -198,7 +210,8 @@ where
.map_err(NoiseError::from);
handshake::rt1_initiator(socket, session,
self.dh_keys.into_identity(),
IdentityExchange::Mutual)
IdentityExchange::Mutual,
self.legacy)
}
}
@@ -221,7 +234,8 @@ where
.map_err(NoiseError::from);
handshake::rt15_responder(socket, session,
self.dh_keys.into_identity(),
IdentityExchange::Mutual)
IdentityExchange::Mutual,
self.legacy)
}
}
@@ -242,7 +256,8 @@ where
.map_err(NoiseError::from);
handshake::rt15_initiator(socket, session,
self.dh_keys.into_identity(),
IdentityExchange::Mutual)
IdentityExchange::Mutual,
self.legacy)
}
}
@@ -265,7 +280,8 @@ where
.map_err(NoiseError::from);
handshake::rt1_responder(socket, session,
self.dh_keys.into_identity(),
IdentityExchange::Receive)
IdentityExchange::Receive,
self.legacy)
}
}
@@ -287,7 +303,8 @@ where
.map_err(NoiseError::from);
handshake::rt1_initiator(socket, session,
self.dh_keys.into_identity(),
IdentityExchange::Send { remote: self.remote.1 })
IdentityExchange::Send { remote: self.remote.1 },
self.legacy)
}
}
@@ -365,3 +382,21 @@ where
}))
}
}
/// Legacy configuration options.
#[derive(Clone)]
pub struct LegacyConfig {
/// Whether to continue sending legacy handshake payloads,
/// i.e. length-prefixed protobuf payloads inside a length-prefixed
/// noise frame. These payloads are not interoperable with other
/// libp2p implementations.
pub send_legacy_handshake: bool,
}
impl Default for LegacyConfig {
fn default() -> Self {
Self {
send_legacy_handshake: false,
}
}
}