Implement onion service Introduce1
This commit is contained in:
parent
dfcbcbce08
commit
1a3b979ecf
|
@ -72,6 +72,9 @@ pub enum RelayMsg {
|
|||
/// Establish Rendezvous
|
||||
#[cfg(feature = "onion-service")]
|
||||
EstablishRendezvous(onion_service::EstablishRendezvous),
|
||||
/// Introduce1
|
||||
#[cfg(feature = "onion-service")]
|
||||
Introduce1(onion_service::Introduce1),
|
||||
|
||||
/// An unrecognized command.
|
||||
Unrecognized(Unrecognized),
|
||||
|
@ -123,6 +126,8 @@ impl RelayMsg {
|
|||
EstablishIntro(_) => RelayCmd::ESTABLISH_INTRO,
|
||||
#[cfg(feature = "onion-service")]
|
||||
EstablishRendezvous(_) => RelayCmd::ESTABLISH_RENDEZVOUS,
|
||||
#[cfg(feature = "onion-service")]
|
||||
Introduce1(_) => RelayCmd::INTRODUCE1,
|
||||
Unrecognized(u) => u.cmd(),
|
||||
}
|
||||
}
|
||||
|
@ -160,6 +165,10 @@ impl RelayMsg {
|
|||
RelayCmd::ESTABLISH_RENDEZVOUS => RelayMsg::EstablishRendezvous(
|
||||
onion_service::EstablishRendezvous::decode_from_reader(r)?,
|
||||
),
|
||||
#[cfg(feature = "onion-service")]
|
||||
RelayCmd::INTRODUCE1 => {
|
||||
RelayMsg::Introduce1(onion_service::Introduce1::decode_from_reader(r)?)
|
||||
}
|
||||
_ => RelayMsg::Unrecognized(Unrecognized::decode_with_cmd(c, r)?),
|
||||
})
|
||||
}
|
||||
|
@ -192,6 +201,8 @@ impl RelayMsg {
|
|||
EstablishIntro(b) => b.encode_onto(w),
|
||||
#[cfg(feature = "onion-service")]
|
||||
EstablishRendezvous(b) => b.encode_onto(w),
|
||||
#[cfg(feature = "onion-service")]
|
||||
Introduce1(b) => b.encode_onto(w),
|
||||
Unrecognized(b) => b.encode_onto(w),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
use super::msg;
|
||||
use caret::caret_int;
|
||||
use tor_bytes::{EncodeError, EncodeResult, Readable, Result, Writeable};
|
||||
use tor_bytes::{EncodeError, EncodeResult, Error as BytesError, Readable, Result, Writeable};
|
||||
use tor_bytes::{Reader, Writer};
|
||||
use tor_units::BoundedInt32;
|
||||
|
||||
|
@ -251,3 +251,65 @@ impl msg::Body for EstablishRendezvous {
|
|||
w.write(&self.cookie)
|
||||
}
|
||||
}
|
||||
|
||||
/// A message sent from client to introduction point.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Introduce1 {
|
||||
/// Introduction point auth key type and the type of
|
||||
/// the MAC used in `handshake_auth`.
|
||||
auth_key_type: AuthKeyType,
|
||||
/// The public introduction point auth key.
|
||||
auth_key: Vec<u8>,
|
||||
/// Up to end of relay payload.
|
||||
encrypted: Vec<u8>,
|
||||
}
|
||||
|
||||
impl msg::Body for Introduce1 {
|
||||
fn into_message(self) -> msg::RelayMsg {
|
||||
msg::RelayMsg::Introduce1(self)
|
||||
}
|
||||
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
|
||||
let legacy_key_id: [u8; 20] = r.extract()?;
|
||||
if legacy_key_id.iter().any(|b| *b != 0_u8) {
|
||||
return Err(BytesError::BadMessage("legacy key id in Introduce1."));
|
||||
}
|
||||
let auth_key_type = r.take_u8()?.into();
|
||||
let auth_key_len = r.take_u16()?;
|
||||
let auth_key = r.take(auth_key_len as usize)?.into();
|
||||
let n_ext = r.take_u8()?;
|
||||
for _ in 0..n_ext {
|
||||
let _ext_type = r.take_u8()?;
|
||||
r.read_nested_u8len(|r| {
|
||||
r.take_rest();
|
||||
Ok(())
|
||||
})?;
|
||||
}
|
||||
let encrypted = r.take_rest().into();
|
||||
Ok(Self {
|
||||
auth_key_type,
|
||||
auth_key,
|
||||
encrypted,
|
||||
})
|
||||
}
|
||||
fn encode_onto(self, w: &mut Vec<u8>) -> EncodeResult<()> {
|
||||
w.write_all(&[0_u8; 20]);
|
||||
w.write_u8(self.auth_key_type.get());
|
||||
w.write_u16(u16::try_from(self.auth_key.len()).map_err(|_| EncodeError::BadLengthValue)?);
|
||||
w.write_all(&self.auth_key[..]);
|
||||
// No Introduce1 extension for now.
|
||||
w.write_u8(0_u8);
|
||||
w.write_all(&self.encrypted[..]);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Introduce1 {
|
||||
/// All arguments constructor
|
||||
pub fn new(auth_key_type: AuthKeyType, auth_key: Vec<u8>, encrypted: Vec<u8>) -> Self {
|
||||
Self {
|
||||
auth_key_type,
|
||||
auth_key,
|
||||
encrypted,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -670,7 +670,7 @@ fn test_establish_intro() {
|
|||
let sig = vec![0, 1, 2, 3];
|
||||
assert_eq!(Into::<u8>::into(cmd), 32);
|
||||
|
||||
// Establish intro with one recognzied extention
|
||||
// Establish intro with one recognzied extension
|
||||
let mut es_intro = EstablishIntro::new(auth_key_type, auth_key, handshake_auth, sig);
|
||||
es_intro.set_extension_dos(extension_dos);
|
||||
msg(
|
||||
|
@ -682,7 +682,7 @@ fn test_establish_intro() {
|
|||
&es_intro.into(),
|
||||
);
|
||||
|
||||
// Establish intro with no extention
|
||||
// Establish intro with no extension
|
||||
let auth_key = vec![0, 1, 2, 3];
|
||||
let sig = vec![0, 1, 2, 3];
|
||||
msg(
|
||||
|
@ -694,11 +694,10 @@ fn test_establish_intro() {
|
|||
&EstablishIntro::new(auth_key_type, auth_key, handshake_auth, sig).into(),
|
||||
);
|
||||
|
||||
// Establish intro with one recognzied extention
|
||||
// and one unknown extention
|
||||
// Establish intro with one recognzied extension
|
||||
// and one unknown extension
|
||||
let auth_key = vec![0, 1, 2, 3];
|
||||
let sig = vec![0, 1, 2, 3];
|
||||
|
||||
let extension_dos = EstIntroExtDoS::new(Some(1_i32), Some(2_i32))
|
||||
.expect("invalid EST_INTRO_DOS_EXT parameter(s)");
|
||||
|
||||
|
@ -721,6 +720,58 @@ fn test_establish_intro() {
|
|||
assert_eq!(actual_bytes, expect_bytes);
|
||||
}
|
||||
|
||||
#[cfg(feature = "onion-service")]
|
||||
#[test]
|
||||
fn test_introduce1() {
|
||||
use tor_cell::relaycell::{
|
||||
msg::RelayMsg,
|
||||
onion_service::{AuthKeyType, Introduce1},
|
||||
};
|
||||
|
||||
let cmd = RelayCmd::INTRODUCE1;
|
||||
let auth_key_type = AuthKeyType::ED25519_SHA3_256;
|
||||
let auth_key = vec![0, 1, 2, 3];
|
||||
let encrypted = vec![1, 9, 8, 4];
|
||||
assert_eq!(Into::<u8>::into(cmd), 34);
|
||||
|
||||
// Introduce1 with no extension
|
||||
let intro1 = Introduce1::new(auth_key_type, auth_key, encrypted);
|
||||
msg(
|
||||
cmd,
|
||||
"0000000000000000000000000000000000000000
|
||||
02 0004 00010203
|
||||
00
|
||||
01090804",
|
||||
&intro1.clone().into(),
|
||||
);
|
||||
|
||||
// Introduce1 with unknown extensions
|
||||
let body = "0000000000000000000000000000000000000000
|
||||
02 0004 00010203
|
||||
02 01 01 00 02 01 00
|
||||
01090804";
|
||||
let actual_msg = decode(cmd, &unhex(body)[..]).unwrap();
|
||||
let mut actual_bytes = vec![];
|
||||
let mut expect_bytes = vec![];
|
||||
actual_msg
|
||||
.encode_onto(&mut actual_bytes)
|
||||
.expect("Encode msg onto byte vector");
|
||||
let expected_msg: RelayMsg = intro1.into();
|
||||
expected_msg
|
||||
.encode_onto(&mut expect_bytes)
|
||||
.expect("Encode msg onto byte vector");
|
||||
assert_eq!(actual_bytes, expect_bytes);
|
||||
|
||||
// Introduce1 with legacy key id
|
||||
msg_error(
|
||||
cmd,
|
||||
"1000000000000000000000000000000000000000
|
||||
02 0004 00010203
|
||||
00
|
||||
01090804",
|
||||
BytesError::BadMessage("legacy key id in Introduce1."),
|
||||
);
|
||||
}
|
||||
// TODO: need to add tests for:
|
||||
// - unrecognized
|
||||
// - data
|
||||
|
|
Loading…
Reference in New Issue