diff --git a/zerotier-network-hypervisor/src/vl1/peer.rs b/zerotier-network-hypervisor/src/vl1/peer.rs index 32359c62f..a876789e7 100644 --- a/zerotier-network-hypervisor/src/vl1/peer.rs +++ b/zerotier-network-hypervisor/src/vl1/peer.rs @@ -1,5 +1,6 @@ // (c) 2020-2022 ZeroTier, Inc. -- currently propritery pending actual release and licensing. See LICENSE.md. +use std::collections::HashMap; use std::hash::{Hash, Hasher}; use std::mem::MaybeUninit; use std::sync::atomic::{AtomicI64, AtomicU64, AtomicU8, Ordering}; @@ -49,6 +50,9 @@ pub struct Peer { // Paths sorted in descending order of quality / preference. paths: Mutex>>, + // External addresses by this peer for the local node. + reported_local_endpoints: Mutex>, + // Statistics and times of events. last_send_time_ticks: AtomicI64, last_receive_time_ticks: AtomicI64, @@ -182,6 +186,7 @@ impl Peer { identity_symmetric_key: SymmetricSecret::new(static_secret), ephemeral_symmetric_key: RwLock::new(None), paths: Mutex::new(Vec::with_capacity(4)), + reported_local_endpoints: Mutex::new(HashMap::new()), last_send_time_ticks: AtomicI64::new(crate::util::NEVER_HAPPENED_TICKS), last_receive_time_ticks: AtomicI64::new(crate::util::NEVER_HAPPENED_TICKS), last_forward_time_ticks: AtomicI64::new(crate::util::NEVER_HAPPENED_TICKS), @@ -441,21 +446,17 @@ impl Peer { let message_id = self.next_message_id(); { - let packet_header: &mut PacketHeader = packet.append_struct_get_mut().unwrap(); - packet_header.id = message_id.to_ne_bytes(); - packet_header.dest = self.identity.address.to_bytes(); - packet_header.src = node.identity.address.to_bytes(); - packet_header.flags_cipher_hops = security_constants::CIPHER_NOCRYPT_POLY1305; - } - - { - let hello_fixed_headers: &mut message_component_structs::HelloFixedHeaderFields = packet.append_struct_get_mut().unwrap(); - hello_fixed_headers.verb = verbs::VL1_HELLO | packet_constants::VERB_FLAG_EXTENDED_AUTHENTICATION; - hello_fixed_headers.version_proto = PROTOCOL_VERSION; - hello_fixed_headers.version_major = VERSION_MAJOR; - hello_fixed_headers.version_minor = VERSION_MINOR; - hello_fixed_headers.version_revision = VERSION_REVISION.to_be_bytes(); - hello_fixed_headers.timestamp = (time_ticks as u64).wrapping_add(self.random_ticks_offset).to_be_bytes(); + let f: &mut (PacketHeader, message_component_structs::HelloFixedHeaderFields) = packet.append_struct_get_mut().unwrap(); + f.0.id = message_id.to_ne_bytes(); + f.0.dest = self.identity.address.to_bytes(); + f.0.src = node.identity.address.to_bytes(); + f.0.flags_cipher_hops = security_constants::CIPHER_NOCRYPT_POLY1305; + f.1.verb = verbs::VL1_HELLO | packet_constants::VERB_FLAG_EXTENDED_AUTHENTICATION; + f.1.version_proto = PROTOCOL_VERSION; + f.1.version_major = VERSION_MAJOR; + f.1.version_minor = VERSION_MINOR; + f.1.version_revision = VERSION_REVISION.to_be_bytes(); + f.1.timestamp = (time_ticks as u64).wrapping_add(self.random_ticks_offset).to_be_bytes(); } debug_assert_eq!(packet.len(), 41); @@ -582,8 +583,6 @@ impl Peer { // If we made it here it decrypted and passed authentication. // --------------------------------------------------------------- - debug_event!(si, "[vl1] #{:0>16x} decrypted and authenticated, verb: {} ({:0>2x})", u64::from_be_bytes(packet_header.id), verbs::name(verb & packet_constants::VERB_MASK), (verb & packet_constants::VERB_MASK) as u32); - if (verb & packet_constants::VERB_FLAG_COMPRESSED) != 0 { let mut decompressed_payload: [u8; packet_constants::SIZE_MAX] = unsafe { MaybeUninit::uninit().assume_init() }; decompressed_payload[0] = verb; @@ -606,6 +605,8 @@ impl Peer { } verb &= packet_constants::VERB_MASK; // mask off flags + debug_event!(si, "[vl1] #{:0>16x} decrypted and authenticated, verb: {} ({:0>2x})", u64::from_be_bytes(packet_header.id), verbs::name(verb & packet_constants::VERB_MASK), verb as u32); + return match verb { verbs::VL1_NOP => true, verbs::VL1_HELLO => self.handle_incoming_hello(si, node, time_ticks, message_id, source_path, &payload).await, @@ -629,33 +630,55 @@ impl Peer { self.remote_protocol_version.store(hello_fixed_headers.version_proto, Ordering::Relaxed); self.remote_version .store((hello_fixed_headers.version_major as u64).wrapping_shl(48) | (hello_fixed_headers.version_minor as u64).wrapping_shl(32) | (u16::from_be_bytes(hello_fixed_headers.version_revision) as u64).wrapping_shl(16), Ordering::Relaxed); + if let Ok(identity) = Identity::unmarshal(payload, &mut cursor) { + if identity.eq(&self.identity) { + if hello_fixed_headers.version_proto >= 20 { + let mut session_metadata_len = payload.read_u16(&mut cursor).unwrap_or(0) as usize; + if session_metadata_len > 16 { + session_metadata_len -= 16; + if let Ok(nonce) = payload.read_bytes_fixed::<16>(&mut cursor) { + let mut nonce = nonce.clone(); + if let Ok(session_metadata) = payload.read_bytes(session_metadata_len, &mut cursor) { + let mut session_metadata = session_metadata.to_vec(); - let mut packet = PacketBuffer::new(); + nonce[12] &= 0x7f; + let salted_key = Secret(hmac_sha384(&message_id.to_ne_bytes(), self.identity_symmetric_key.hello_private_section_key.as_bytes())); + let mut aes = AesCtr::new(&salted_key.as_bytes()[0..32]); + aes.init(&nonce); + aes.crypt_in_place(session_metadata.as_mut_slice()); - packet.set_size(packet_constants::HEADER_SIZE); - { - let fixed_fields: &mut message_component_structs::OkHeader = packet.append_struct_get_mut().unwrap(); - fixed_fields.verb = verbs::VL1_OK; - fixed_fields.in_re_verb = verbs::VL1_HELLO; - fixed_fields.in_re_message_id = message_id.to_ne_bytes(); + if let Some(_session_metadata) = Dictionary::from_bytes(session_metadata.as_slice()) { + // TODO + } + } + } + } + } + + let mut packet = PacketBuffer::new(); + packet.set_size(packet_constants::HEADER_SIZE); + { + let f: &mut (message_component_structs::OkHeader, message_component_structs::OkHelloFixedHeaderFields) = packet.append_struct_get_mut().unwrap(); + f.0.verb = verbs::VL1_OK; + f.0.in_re_verb = verbs::VL1_HELLO; + f.0.in_re_message_id = message_id.to_ne_bytes(); + f.1.timestamp_echo = hello_fixed_headers.timestamp; + f.1.version_proto = PROTOCOL_VERSION; + f.1.version_major = VERSION_MAJOR; + f.1.version_minor = VERSION_MINOR; + f.1.version_revision = VERSION_REVISION.to_be_bytes(); + } + + if hello_fixed_headers.version_proto >= 20 { + let session_metadata = self.create_session_metadata(node, &source_path.endpoint); + assert!(session_metadata.len() <= 0xffff); // sanity check, should be impossible + assert!(packet.append_u16(session_metadata.len() as u16).is_ok()); + assert!(packet.append_bytes(session_metadata.as_slice()).is_ok()); + } + + return self.send(si, node, time_ticks, self.next_message_id(), &mut packet).await; + } } - { - let fixed_fields: &mut message_component_structs::OkHelloFixedHeaderFields = packet.append_struct_get_mut().unwrap(); - fixed_fields.timestamp_echo = hello_fixed_headers.timestamp; - fixed_fields.version_proto = PROTOCOL_VERSION; - fixed_fields.version_major = VERSION_MAJOR; - fixed_fields.version_minor = VERSION_MINOR; - fixed_fields.version_revision = VERSION_REVISION.to_be_bytes(); - } - - if hello_fixed_headers.version_proto >= 20 { - let session_metadata = self.create_session_metadata(node, &source_path.endpoint); - assert!(session_metadata.len() <= 0xffff); // sanity check, should be impossible - assert!(packet.append_u16(session_metadata.len() as u16).is_ok()); - assert!(packet.append_bytes(session_metadata.as_slice()).is_ok()); - } - - return self.send(si, node, time_ticks, self.next_message_id(), &mut packet).await; } return false; } @@ -707,8 +730,9 @@ impl Peer { } } } else { - //let physical_address = Endpoint::unmarshal(&payload, &mut cursor); - // TODO + if let Ok(reported_endpoint) = Endpoint::unmarshal(&payload, &mut cursor) { + let _ = self.reported_local_endpoints.lock().insert(reported_endpoint, time_ticks); + } } if hops == 0 && !path_is_known { diff --git a/zerotier-system-service/Cargo.lock b/zerotier-system-service/Cargo.lock index 67df8be03..62920cae0 100644 --- a/zerotier-system-service/Cargo.lock +++ b/zerotier-system-service/Cargo.lock @@ -118,9 +118,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.2.6" +version = "3.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1fe12880bae935d142c8702d500c63a4e8634b6c3c57ad72bf978fc7b6249a" +checksum = "5b7b16274bb247b45177db843202209b12191b631a14a9d06e41b3777d6ecf14" dependencies = [ "bitflags", "clap_lex", @@ -131,9 +131,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87eba3c8c7f42ef17f6c659fc7416d0f4758cd3e58861ee63c5fa4a4dde649e4" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" dependencies = [ "os_str_bytes", ] @@ -637,7 +637,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.10", + "semver 1.0.11", ] [[package]] @@ -663,9 +663,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41d061efea015927ac527063765e73601444cdc344ba855bc7bd44578b25e1c" +checksum = "3d92beeab217753479be2f74e54187a6aed4c125ff0703a866c3147a02f0c6dd" [[package]] name = "semver-parser" @@ -695,9 +695,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" dependencies = [ "itoa", "ryu", @@ -734,9 +734,9 @@ checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" [[package]] name = "smallvec" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2" [[package]] name = "socket2"