1use super::{BoxedCellBody, CELL_DATA_LEN, ChanCmd, RawCellBody};
4use std::net::{IpAddr, Ipv4Addr};
5
6use tor_basic_utils::skip_fmt;
7use tor_bytes::{self, EncodeError, EncodeResult, Error, Readable, Reader, Result, Writer};
8use tor_memquota::derive_deftly_template_HasMemoryCost;
9use tor_units::IntegerMilliseconds;
10
11use caret::caret_int;
12use derive_deftly::Deftly;
13use educe::Educe;
14
15pub trait Body: Readable {
17 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
19 r.extract()
20 }
21 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()>;
26}
27
28crate::restrict::restricted_msg! {
29#[derive(Clone, Debug, Deftly)]
35#[derive_deftly(HasMemoryCost)]
36#[non_exhaustive]
37@omit_from "avoid_conflict_with_a_blanket_implementation"
38pub enum AnyChanMsg : ChanMsg {
39 Padding,
41 Vpadding,
43 Create,
45 CreateFast,
47 Create2,
49 Created,
51 CreatedFast,
53 Created2,
55 Relay,
57 RelayEarly,
59 Destroy,
61 Netinfo,
63 Versions,
66 PaddingNegotiate,
68 Certs,
71 AuthChallenge,
74 Authenticate,
77 _ =>
78 Unrecognized,
80}
81}
82
83#[derive(Clone, Debug, Default, Deftly)]
91#[derive_deftly(HasMemoryCost)]
92#[non_exhaustive]
93pub struct Padding {}
94impl Padding {
95 pub fn new() -> Self {
97 Padding {}
98 }
99}
100impl Body for Padding {
101 fn encode_onto<W: Writer + ?Sized>(self, _w: &mut W) -> EncodeResult<()> {
102 Ok(())
103 }
104}
105impl Readable for Padding {
106 fn take_from(_b: &mut Reader<'_>) -> Result<Self> {
107 Ok(Padding {})
108 }
109}
110
111#[derive(Clone, Debug, Deftly)]
115#[derive_deftly(HasMemoryCost)]
116pub struct Vpadding {
117 len: u16,
119}
120impl Vpadding {
121 pub fn new(len: u16) -> Self {
123 Vpadding { len }
124 }
125}
126impl Body for Vpadding {
127 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
128 w.write_zeros(self.len as usize);
129 Ok(())
130 }
131}
132impl Readable for Vpadding {
133 fn take_from(b: &mut Reader<'_>) -> Result<Self> {
134 if b.remaining() > u16::MAX as usize {
135 return Err(Error::InvalidMessage(
136 "Too many bytes in VPADDING cell".into(),
137 ));
138 }
139 Ok(Vpadding {
140 len: b.remaining() as u16,
141 })
142 }
143}
144
145macro_rules! fixed_len_handshake {
148 {
149 $(#[$meta:meta])*
150 $name:ident , $cmd:ident, $len:ident
151 } => {
152 $(#[$meta])*
153 #[derive(Clone,Debug,Deftly)]
154 #[derive_deftly(HasMemoryCost)]
155 pub struct $name {
156 handshake: Vec<u8>
157 }
158 impl $name {
159 pub fn new<B>(handshake: B) -> Self
161 where B: Into<Vec<u8>>
162 {
163 let handshake = handshake.into();
164 $name { handshake }
165 }
166 }
167 impl Body for $name {
168 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
169 w.write_all(&self.handshake[..]);
170 Ok(())
171 }
172 }
173 impl Readable for $name {
174 fn take_from(b: &mut Reader<'_>) -> Result<Self> {
175 Ok($name {
176 handshake: b.take($len)?.into(),
177 })
178 }
179 }
180 }
181}
182
183pub(crate) const TAP_C_HANDSHAKE_LEN: usize = 128 + 16 + 42;
185pub(crate) const TAP_S_HANDSHAKE_LEN: usize = 128 + 20;
187
188const FAST_C_HANDSHAKE_LEN: usize = 20;
190const FAST_S_HANDSHAKE_LEN: usize = 20 + 20;
192
193fixed_len_handshake! {
194 Create, CREATE, TAP_C_HANDSHAKE_LEN
203}
204fixed_len_handshake! {
205 Created, CREATED, TAP_S_HANDSHAKE_LEN
210}
211fixed_len_handshake! {
212 CreateFast, CREATE_FAST, FAST_C_HANDSHAKE_LEN
224}
225impl CreateFast {
226 pub fn handshake(&self) -> &[u8] {
228 &self.handshake
229 }
230}
231fixed_len_handshake! {
232 CreatedFast, CREATED_FAST, FAST_S_HANDSHAKE_LEN
237}
238impl CreatedFast {
239 pub fn into_handshake(self) -> Vec<u8> {
241 self.handshake
242 }
243}
244
245caret_int! {
246 #[derive(Deftly)]
249 #[derive_deftly(HasMemoryCost)]
250 pub struct HandshakeType(u16) {
251 TAP = 0,
253
254 NTOR = 2,
258 NTOR_V3 = 3,
260 }
261}
262
263#[derive(Clone, Debug, Deftly)]
272#[derive_deftly(HasMemoryCost)]
273pub struct Create2 {
274 handshake_type: HandshakeType,
276 handshake: Vec<u8>,
278}
279impl Body for Create2 {
280 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
281 w.write_u16(self.handshake_type.into());
282 let handshake_len = self
283 .handshake
284 .len()
285 .try_into()
286 .map_err(|_| EncodeError::BadLengthValue)?;
287 w.write_u16(handshake_len);
288 w.write_all(&self.handshake[..]);
289 Ok(())
290 }
291}
292impl Readable for Create2 {
293 fn take_from(b: &mut Reader<'_>) -> Result<Self> {
294 let handshake_type = HandshakeType::from(b.take_u16()?);
295 let hlen = b.take_u16()?;
296 let handshake = b.take(hlen as usize)?.into();
297 Ok(Create2 {
298 handshake_type,
299 handshake,
300 })
301 }
302}
303impl Create2 {
304 pub fn new<B>(handshake_type: HandshakeType, handshake: B) -> Self
306 where
307 B: Into<Vec<u8>>,
308 {
309 let handshake = handshake.into();
310 Create2 {
311 handshake_type,
312 handshake,
313 }
314 }
315
316 pub fn handshake_type(&self) -> HandshakeType {
318 self.handshake_type
319 }
320
321 pub fn body(&self) -> &[u8] {
323 &self.handshake[..]
324 }
325}
326
327#[derive(Clone, Debug, Deftly)]
332#[derive_deftly(HasMemoryCost)]
333pub struct Created2 {
334 handshake: Vec<u8>,
336}
337impl Created2 {
338 pub fn new<B>(handshake: B) -> Self
340 where
341 B: Into<Vec<u8>>,
342 {
343 let handshake = handshake.into();
344 Created2 { handshake }
345 }
346 pub fn into_body(self) -> Vec<u8> {
348 self.handshake
349 }
350}
351impl Body for Created2 {
352 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
353 let handshake_len = self
354 .handshake
355 .len()
356 .try_into()
357 .map_err(|_| EncodeError::BadLengthValue)?;
358 w.write_u16(handshake_len);
359 w.write_all(&self.handshake[..]);
360 Ok(())
361 }
362}
363impl Readable for Created2 {
364 fn take_from(b: &mut Reader<'_>) -> Result<Self> {
365 let hlen = b.take_u16()?;
366 let handshake = b.take(hlen as usize)?.into();
367 Ok(Created2 { handshake })
368 }
369}
370
371#[derive(Clone, Educe, derive_more::From, Deftly)]
382#[derive_deftly(HasMemoryCost)]
383#[educe(Debug)]
384pub struct Relay {
385 #[educe(Debug(method = "skip_fmt"))]
393 body: BoxedCellBody,
394}
395impl Relay {
396 pub fn new<P>(body: P) -> Self
398 where
399 P: AsRef<[u8]>,
400 {
401 let body = body.as_ref();
402 let mut r = [0_u8; CELL_DATA_LEN];
403 r[..body.len()].copy_from_slice(body);
406 Relay { body: Box::new(r) }
407 }
408 pub fn from_raw(body: RawCellBody) -> Self {
410 Relay {
411 body: Box::new(body),
412 }
413 }
414 pub fn into_relay_body(self) -> BoxedCellBody {
417 self.body
418 }
419 pub fn into_early(self) -> AnyChanMsg {
421 AnyChanMsg::RelayEarly(RelayEarly(self))
422 }
423}
424impl Body for Relay {
425 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
426 w.write_all(&self.body[..]);
427 Ok(())
428 }
429}
430impl Readable for Relay {
431 fn take_from(b: &mut Reader<'_>) -> Result<Self> {
432 let mut body = Box::new([0_u8; CELL_DATA_LEN]);
433 body.copy_from_slice(b.take(CELL_DATA_LEN)?);
434 Ok(Relay { body })
435 }
436}
437
438#[derive(Clone, Debug, derive_more::Deref, derive_more::From, derive_more::Into, Deftly)]
442#[derive_deftly(HasMemoryCost)]
443pub struct RelayEarly(Relay);
444impl Readable for RelayEarly {
445 fn take_from(r: &mut Reader<'_>) -> Result<Self> {
446 Ok(RelayEarly(Relay::take_from(r)?))
447 }
448}
449impl Body for RelayEarly {
450 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
451 self.0.encode_onto(w)
452 }
453}
454impl RelayEarly {
455 pub fn into_relay_body(self) -> BoxedCellBody {
461 self.0.body
462 }
463}
464
465#[derive(Clone, Debug, Deftly)]
471#[derive_deftly(HasMemoryCost)]
472pub struct Destroy {
473 reason: DestroyReason,
475}
476impl Destroy {
477 pub fn new(reason: DestroyReason) -> Self {
479 Destroy { reason }
480 }
481 pub fn reason(&self) -> DestroyReason {
483 self.reason
484 }
485}
486impl Body for Destroy {
487 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
488 w.write_u8(self.reason.into());
489 Ok(())
490 }
491}
492impl Readable for Destroy {
493 fn take_from(r: &mut Reader<'_>) -> Result<Self> {
494 let reason = r.take_u8()?.into();
495 Ok(Destroy { reason })
496 }
497}
498
499caret_int! {
500 #[derive(Deftly)]
502 #[derive_deftly(HasMemoryCost)]
503 pub struct DestroyReason(u8) {
504 NONE = 0,
508 PROTOCOL = 1,
510 INTERNAL = 2,
512 REQUESTED = 3,
514 HIBERNATING = 4,
516 RESOURCELIMIT = 5,
518 CONNECTFAILED = 6,
520 OR_IDENTITY = 7,
522 CHANNEL_CLOSED = 8,
524 FINISHED = 9,
526 TIMEOUT = 10,
528 DESTROYED = 11,
530 NOSUCHSERVICE = 12
532 }
533}
534
535impl DestroyReason {
536 pub fn human_str(&self) -> &'static str {
538 match *self {
539 DestroyReason::NONE => "No reason",
540 DestroyReason::PROTOCOL => "Protocol violation",
541 DestroyReason::INTERNAL => "Internal error",
542 DestroyReason::REQUESTED => "Client sent a TRUNCATE command",
543 DestroyReason::HIBERNATING => "Relay is hibernating and not accepting requests",
544 DestroyReason::RESOURCELIMIT => "Relay ran out of resources",
545 DestroyReason::CONNECTFAILED => "Couldn't connect to relay",
546 DestroyReason::OR_IDENTITY => "Connected to relay with different OR identity",
547 DestroyReason::CHANNEL_CLOSED => "The OR channels carrying this circuit died",
548 DestroyReason::FINISHED => "Circuit expired for being too dirty or old",
549 DestroyReason::TIMEOUT => "Circuit construction took too long",
550 DestroyReason::DESTROYED => "Circuit was destroyed without client truncate",
551 DestroyReason::NOSUCHSERVICE => "No such onion service",
552 _ => "Unrecognized reason",
553 }
554 }
555}
556
557#[derive(Clone, Debug, Deftly)]
565#[derive_deftly(HasMemoryCost)]
566pub struct Netinfo {
567 timestamp: u32,
573 their_addr: Option<IpAddr>,
575 my_addr: Vec<IpAddr>,
577}
578fn enc_one_netinfo_addr<W: Writer + ?Sized>(w: &mut W, addr: &IpAddr) {
580 match addr {
581 IpAddr::V4(ipv4) => {
582 w.write_u8(0x04); w.write_u8(4); w.write_all(&ipv4.octets()[..]);
585 }
586 IpAddr::V6(ipv6) => {
587 w.write_u8(0x06); w.write_u8(16); w.write_all(&ipv6.octets()[..]);
590 }
591 }
592}
593fn take_one_netinfo_addr(r: &mut Reader<'_>) -> Result<Option<IpAddr>> {
595 let atype = r.take_u8()?;
596 let alen = r.take_u8()?;
597 let abody = r.take(alen as usize)?;
598 match (atype, alen) {
599 (0x04, 4) => {
600 let bytes = [abody[0], abody[1], abody[2], abody[3]];
601 Ok(Some(IpAddr::V4(bytes.into())))
602 }
603 (0x06, 16) => {
604 let mut bytes = [0_u8; 16];
606 bytes.copy_from_slice(abody);
607 Ok(Some(IpAddr::V6(bytes.into())))
608 }
609 (_, _) => Ok(None),
610 }
611}
612impl Netinfo {
613 pub fn from_client(their_addr: Option<IpAddr>) -> Self {
615 Netinfo {
616 timestamp: 0, their_addr,
618 my_addr: Vec::new(), }
620 }
621 pub fn from_relay<V>(timestamp: u32, their_addr: Option<IpAddr>, my_addrs: V) -> Self
623 where
624 V: Into<Vec<IpAddr>>,
625 {
626 let my_addr = my_addrs.into();
627 Netinfo {
628 timestamp,
629 their_addr,
630 my_addr,
631 }
632 }
633 pub fn timestamp(&self) -> Option<std::time::SystemTime> {
635 use std::time::{Duration, SystemTime};
636 if self.timestamp == 0 {
637 None
638 } else {
639 Some(SystemTime::UNIX_EPOCH + Duration::from_secs(self.timestamp.into()))
640 }
641 }
642
643 pub fn their_addr(&self) -> Option<&IpAddr> {
647 self.their_addr.as_ref()
648 }
649
650 pub fn my_addrs(&self) -> &[IpAddr] {
652 &self.my_addr
653 }
654}
655impl Body for Netinfo {
656 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
657 w.write_u32(self.timestamp);
658 let their_addr = self
659 .their_addr
660 .unwrap_or_else(|| Ipv4Addr::UNSPECIFIED.into());
661 enc_one_netinfo_addr(w, &their_addr);
662 let n_addrs: u8 = self
663 .my_addr
664 .len()
665 .try_into()
666 .map_err(|_| EncodeError::BadLengthValue)?;
667 w.write_u8(n_addrs);
668 for addr in &self.my_addr {
669 enc_one_netinfo_addr(w, addr);
670 }
671 Ok(())
672 }
673}
674impl Readable for Netinfo {
675 fn take_from(r: &mut Reader<'_>) -> Result<Self> {
676 let timestamp = r.take_u32()?;
677 let their_addr = take_one_netinfo_addr(r)?.filter(|a| !a.is_unspecified());
678 let my_n_addrs = r.take_u8()?;
679 let mut my_addr = Vec::with_capacity(my_n_addrs as usize);
680 for _ in 0..my_n_addrs {
681 if let Some(a) = take_one_netinfo_addr(r)? {
682 my_addr.push(a);
683 }
684 }
685 Ok(Netinfo {
686 timestamp,
687 their_addr,
688 my_addr,
689 })
690 }
691}
692
693#[derive(Clone, Debug, Deftly)]
703#[derive_deftly(HasMemoryCost)]
704pub struct Versions {
705 versions: Vec<u16>,
707}
708impl Versions {
709 pub fn new<B>(vs: B) -> crate::Result<Self>
714 where
715 B: Into<Vec<u16>>,
716 {
717 let versions = vs.into();
718 if versions.len() < (u16::MAX / 2) as usize {
719 Ok(Self { versions })
720 } else {
721 Err(crate::Error::CantEncode("Too many versions"))
722 }
723 }
724 pub fn encode_for_handshake(self) -> EncodeResult<Vec<u8>> {
730 let mut v = Vec::new();
731 v.write_u16(0); v.write_u8(ChanCmd::VERSIONS.into());
733 v.write_u16((self.versions.len() * 2) as u16); self.encode_onto(&mut v)?;
735 Ok(v)
736 }
737 pub fn best_shared_link_protocol(&self, my_protos: &[u16]) -> Option<u16> {
740 let p = my_protos
743 .iter()
744 .filter(|p| self.versions.contains(p))
745 .fold(0_u16, |a, b| u16::max(a, *b));
746 if p == 0 { None } else { Some(p) }
747 }
748}
749impl Body for Versions {
750 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
751 for v in &self.versions {
752 w.write_u16(*v);
753 }
754 Ok(())
755 }
756}
757impl Readable for Versions {
758 fn take_from(r: &mut Reader<'_>) -> Result<Self> {
759 let mut versions = Vec::new();
760 while r.remaining() > 0 {
761 versions.push(r.take_u16()?);
762 }
763 Ok(Versions { versions })
764 }
765}
766
767caret_int! {
768 #[derive(Deftly)]
771 #[derive_deftly(HasMemoryCost)]
772 pub struct PaddingNegotiateCmd(u8) {
773 START = 2,
775
776 STOP = 1,
778 }
779}
780
781#[derive(Clone, Debug, Eq, PartialEq, Deftly)]
793#[derive_deftly(HasMemoryCost)]
794pub struct PaddingNegotiate {
795 command: PaddingNegotiateCmd,
797 ito_low_ms: u16,
800 ito_high_ms: u16,
803}
804impl PaddingNegotiate {
805 pub fn start_default() -> Self {
809 Self {
811 command: PaddingNegotiateCmd::START,
812 ito_low_ms: 0,
813 ito_high_ms: 0,
814 }
815 }
816
817 pub fn start(ito_low: IntegerMilliseconds<u16>, ito_high: IntegerMilliseconds<u16>) -> Self {
819 Self {
821 command: PaddingNegotiateCmd::START,
822 ito_low_ms: ito_low.as_millis(),
823 ito_high_ms: ito_high.as_millis(),
824 }
825 }
826
827 pub fn stop() -> Self {
829 Self {
831 command: PaddingNegotiateCmd::STOP,
832 ito_low_ms: 0,
833 ito_high_ms: 0,
834 }
835 }
836
837 #[cfg(feature = "testing")]
841 pub fn from_raw(command: PaddingNegotiateCmd, ito_low_ms: u16, ito_high_ms: u16) -> Self {
842 PaddingNegotiate {
843 command,
844 ito_low_ms,
845 ito_high_ms,
846 }
847 }
848}
849impl Default for PaddingNegotiate {
850 fn default() -> Self {
851 Self::start_default()
852 }
853}
854
855impl Body for PaddingNegotiate {
856 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
857 w.write_u8(0); w.write_u8(self.command.get());
859 w.write_u16(self.ito_low_ms);
860 w.write_u16(self.ito_high_ms);
861 Ok(())
862 }
863}
864impl Readable for PaddingNegotiate {
865 fn take_from(r: &mut Reader<'_>) -> Result<Self> {
866 let v = r.take_u8()?;
867 if v != 0 {
868 return Err(Error::InvalidMessage(
869 "Unrecognized padding negotiation version".into(),
870 ));
871 }
872 let command = r.take_u8()?.into();
873 let ito_low_ms = r.take_u16()?;
874 let ito_high_ms = r.take_u16()?;
875 Ok(PaddingNegotiate {
876 command,
877 ito_low_ms,
878 ito_high_ms,
879 })
880 }
881}
882
883#[derive(Clone, Debug, Deftly)]
888#[derive_deftly(HasMemoryCost)]
889struct TorCert {
890 certtype: u8,
892 cert: Vec<u8>,
894}
895fn enc_one_tor_cert<W: Writer + ?Sized>(w: &mut W, c: &TorCert) -> EncodeResult<()> {
897 w.write_u8(c.certtype);
898 let cert_len: u16 = c
899 .cert
900 .len()
901 .try_into()
902 .map_err(|_| EncodeError::BadLengthValue)?;
903 w.write_u16(cert_len);
904 w.write_all(&c.cert[..]);
905 Ok(())
906}
907fn take_one_tor_cert(r: &mut Reader<'_>) -> Result<TorCert> {
909 let certtype = r.take_u8()?;
910 let certlen = r.take_u16()?;
911 let cert = r.take(certlen as usize)?;
912 Ok(TorCert {
913 certtype,
914 cert: cert.into(),
915 })
916}
917#[derive(Clone, Debug, Deftly)]
927#[derive_deftly(HasMemoryCost)]
928pub struct Certs {
929 certs: Vec<TorCert>,
931}
932impl Certs {
933 pub fn new_empty() -> Self {
935 Certs { certs: Vec::new() }
936 }
937 pub fn push_cert_body<B>(&mut self, certtype: tor_cert::CertType, cert: B)
941 where
942 B: Into<Vec<u8>>,
943 {
944 let certtype = certtype.into();
945 let cert = cert.into();
946 self.certs.push(TorCert { certtype, cert });
947 }
948
949 #[cfg(feature = "relay")]
952 pub fn push_cert<C>(&mut self, cert: &C)
953 where
954 C: tor_cert::EncodedCert,
955 {
956 self.push_cert_body(cert.cert_type(), cert.encoded());
957 }
958
959 pub fn cert_body(&self, tp: tor_cert::CertType) -> Option<&[u8]> {
961 let tp: u8 = tp.into();
962 self.certs
963 .iter()
964 .find(|c| c.certtype == tp)
965 .map(|c| &c.cert[..])
966 }
967
968 pub fn parse_ed_cert(&self, tp: tor_cert::CertType) -> crate::Result<tor_cert::KeyUnknownCert> {
971 let body = self
972 .cert_body(tp)
973 .ok_or_else(|| crate::Error::ChanProto(format!("Missing {} certificate", tp)))?;
974
975 let cert = tor_cert::Ed25519Cert::decode(body).map_err(|be| crate::Error::BytesErr {
976 err: be,
977 parsed: "ed25519 certificate",
978 })?;
979 if cert.peek_cert_type() != tp {
980 return Err(crate::Error::ChanProto(format!(
981 "Found a {} certificate labeled as {}",
982 cert.peek_cert_type(),
983 tp
984 )));
985 }
986
987 Ok(cert)
988 }
989}
990
991impl Body for Certs {
992 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
993 let n_certs: u8 = self
994 .certs
995 .len()
996 .try_into()
997 .map_err(|_| EncodeError::BadLengthValue)?;
998 w.write_u8(n_certs);
999 for c in &self.certs {
1000 enc_one_tor_cert(w, c)?;
1001 }
1002 Ok(())
1003 }
1004}
1005impl Readable for Certs {
1006 fn take_from(r: &mut Reader<'_>) -> Result<Self> {
1007 let n = r.take_u8()?;
1008 let mut certs = Vec::new();
1009 for _ in 0..n {
1010 certs.push(take_one_tor_cert(r)?);
1011 }
1012 Ok(Certs { certs })
1013 }
1014}
1015
1016const CHALLENGE_LEN: usize = 32;
1018
1019#[derive(Clone, Debug, Deftly)]
1028#[derive_deftly(HasMemoryCost)]
1029pub struct AuthChallenge {
1030 challenge: [u8; CHALLENGE_LEN],
1032 methods: Vec<u16>,
1034}
1035impl AuthChallenge {
1036 pub fn new<B, M>(challenge: B, methods: M) -> Self
1039 where
1040 B: Into<[u8; CHALLENGE_LEN]>,
1041 M: Into<Vec<u16>>,
1042 {
1043 AuthChallenge {
1044 challenge: challenge.into(),
1045 methods: methods.into(),
1046 }
1047 }
1048
1049 pub fn methods(&self) -> &[u16] {
1051 &self.methods
1052 }
1053}
1054
1055impl Body for AuthChallenge {
1056 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1057 w.write_all(&self.challenge[..]);
1058 let n_methods = self
1059 .methods
1060 .len()
1061 .try_into()
1062 .map_err(|_| EncodeError::BadLengthValue)?;
1063 w.write_u16(n_methods);
1064 for m in self.methods {
1065 w.write_u16(m);
1066 }
1067 Ok(())
1068 }
1069}
1070impl Readable for AuthChallenge {
1071 fn take_from(r: &mut Reader<'_>) -> Result<Self> {
1072 let challenge = r.extract()?;
1074 let n_methods = r.take_u16()?;
1075 let mut methods = Vec::new();
1076 for _ in 0..n_methods {
1077 methods.push(r.take_u16()?);
1078 }
1079 Ok(AuthChallenge { challenge, methods })
1080 }
1081}
1082
1083#[derive(Clone, Debug, Deftly, Eq, PartialEq)]
1090#[derive_deftly(HasMemoryCost)]
1091pub struct Authenticate {
1092 authtype: u16,
1094 auth: Vec<u8>,
1096}
1097impl Authenticate {
1098 const SIG_LEN: usize = 64;
1100
1101 pub fn new<B>(authtype: u16, body: B) -> Self
1103 where
1104 B: Into<Vec<u8>>,
1105 {
1106 Authenticate {
1107 authtype,
1108 auth: body.into(),
1109 }
1110 }
1111
1112 pub fn auth_type(&self) -> u16 {
1114 self.authtype
1115 }
1116
1117 pub fn body_no_rand(&self) -> Result<&[u8]> {
1120 const RAND_LEN: usize = 24;
1122 let body = self.body()?;
1123 let body_end_offset = body.len().checked_sub(RAND_LEN).ok_or(Error::MissingData)?;
1124 Ok(&body[..body_end_offset])
1125 }
1126
1127 pub fn body(&self) -> Result<&[u8]> {
1129 let auth = self.auth();
1130 let sig_end_offset = auth
1131 .len()
1132 .checked_sub(Self::SIG_LEN)
1133 .ok_or(Error::MissingData)?;
1134 Ok(&auth[..sig_end_offset])
1135 }
1136
1137 pub fn auth(&self) -> &[u8] {
1139 &self.auth
1140 }
1141
1142 pub fn sig(&self) -> Result<&[u8; Self::SIG_LEN]> {
1144 let auth = self.auth();
1145 let sig_start_offset = auth
1146 .len()
1147 .checked_sub(Self::SIG_LEN)
1148 .ok_or(Error::MissingData)?;
1149 (&self.auth[sig_start_offset..])
1150 .try_into()
1151 .map_err(|_| Error::Bug(tor_error::internal!("Failed to get signature bytes")))
1152 }
1153}
1154impl Body for Authenticate {
1155 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1156 w.write_u16(self.authtype);
1157 let authlen = self
1158 .auth
1159 .len()
1160 .try_into()
1161 .map_err(|_| EncodeError::BadLengthValue)?;
1162 w.write_u16(authlen);
1163 w.write_all(&self.auth[..]);
1164 Ok(())
1165 }
1166}
1167impl Readable for Authenticate {
1168 fn take_from(r: &mut Reader<'_>) -> Result<Self> {
1169 let authtype = r.take_u16()?;
1170 let authlen = r.take_u16()?;
1171 let auth = r.take(authlen as usize)?.into();
1172 Ok(Authenticate { authtype, auth })
1173 }
1174}
1175
1176#[derive(Clone, Debug, Deftly)]
1184#[derive_deftly(HasMemoryCost)]
1185pub struct Unrecognized {
1186 cmd: ChanCmd,
1188 content: Vec<u8>,
1190}
1191impl Unrecognized {
1192 pub fn new<B>(cmd: ChanCmd, content: B) -> Self
1194 where
1195 B: Into<Vec<u8>>,
1196 {
1197 let content = content.into();
1198 Unrecognized { cmd, content }
1199 }
1200 pub fn cmd(&self) -> ChanCmd {
1202 self.cmd
1203 }
1204 pub fn decode_with_cmd(cmd: ChanCmd, r: &mut Reader<'_>) -> Result<Unrecognized> {
1207 let mut u = Unrecognized::take_from(r)?;
1208 u.cmd = cmd;
1209 Ok(u)
1210 }
1211}
1212impl Body for Unrecognized {
1213 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1214 w.write_all(&self.content[..]);
1215 Ok(())
1216 }
1217}
1218impl Readable for Unrecognized {
1219 fn take_from(r: &mut Reader<'_>) -> Result<Self> {
1220 Ok(Unrecognized {
1221 cmd: 0.into(),
1222 content: r.take(r.remaining())?.into(),
1223 })
1224 }
1225}
1226
1227macro_rules! msg_into_cell {
1230 ($body:ident) => {
1231 impl From<$body> for super::AnyChanCell {
1232 fn from(body: $body) -> super::AnyChanCell {
1233 super::AnyChanCell {
1234 circid: None,
1235 msg: body.into(),
1236 }
1237 }
1238 }
1239 };
1240}
1241
1242msg_into_cell!(Padding);
1243msg_into_cell!(Vpadding);
1244msg_into_cell!(Netinfo);
1245msg_into_cell!(Versions);
1246msg_into_cell!(PaddingNegotiate);
1247msg_into_cell!(Certs);
1248msg_into_cell!(AuthChallenge);
1249msg_into_cell!(Authenticate);
1250
1251macro_rules! msg_impl_chanmsg {
1261 ($($body:ident,)*) =>
1262 {paste::paste!{
1263 $(impl crate::chancell::ChanMsg for $body {
1264 fn cmd(&self) -> crate::chancell::ChanCmd { crate::chancell::ChanCmd::[< $body:snake:upper >] }
1265 fn encode_onto<W: tor_bytes::Writer + ?Sized>(self, w: &mut W) -> tor_bytes::EncodeResult<()> {
1266 crate::chancell::msg::Body::encode_onto(self, w)
1267 }
1268 fn decode_from_reader(cmd: ChanCmd, r: &mut tor_bytes::Reader<'_>) -> tor_bytes::Result<Self> {
1269 if cmd != crate::chancell::ChanCmd::[< $body:snake:upper >] {
1270 return Err(tor_bytes::Error::InvalidMessage(
1271 format!("Expected {} command; got {cmd}", stringify!([< $body:snake:upper >])).into()
1272 ));
1273 }
1274 crate::chancell::msg::Body::decode_from_reader(r)
1275 }
1276 })*
1277 }}
1278}
1279
1280msg_impl_chanmsg!(
1283 Padding,
1284 Vpadding,
1285 Create,
1286 CreateFast,
1287 Create2,
1288 Created,
1289 CreatedFast,
1290 Created2,
1291 Relay,
1292 RelayEarly,
1293 Destroy,
1294 Netinfo,
1295 Versions,
1296 PaddingNegotiate,
1297 Certs,
1298 AuthChallenge,
1299 Authenticate,
1300);
1301
1302#[cfg(test)]
1303mod test {
1304 #![allow(clippy::bool_assert_comparison)]
1306 #![allow(clippy::clone_on_copy)]
1307 #![allow(clippy::dbg_macro)]
1308 #![allow(clippy::mixed_attributes_style)]
1309 #![allow(clippy::print_stderr)]
1310 #![allow(clippy::print_stdout)]
1311 #![allow(clippy::single_char_pattern)]
1312 #![allow(clippy::unwrap_used)]
1313 #![allow(clippy::unchecked_time_subtraction)]
1314 #![allow(clippy::useless_vec)]
1315 #![allow(clippy::needless_pass_by_value)]
1316 use super::*;
1318 #[test]
1319 fn destroy_reason() {
1320 let r1 = DestroyReason::CONNECTFAILED;
1321
1322 assert_eq!(r1.human_str(), "Couldn't connect to relay");
1323
1324 let r2 = DestroyReason::from(200); assert_eq!(r2.human_str(), "Unrecognized reason");
1326 }
1327}