From f059e0402e2e190583bed07abcfc8b3c477be6bd Mon Sep 17 00:00:00 2001 From: pradt2 Date: Thu, 21 Apr 2022 20:36:00 +0100 Subject: [PATCH] WIP towards Geo information --- Cargo.lock | 39 - Cargo.toml | 1 - src/geoip.rs | 2 - src/main.rs | 7 +- src/stun_client.rs | 492 ------- src/stun_client_2.rs | 1274 ----------------- src/stun_codec/attrs/alternate_server.rs | 50 + src/stun_codec/attrs/base/malformed.rs | 38 + src/stun_codec/attrs/base/mod.rs | 7 + src/stun_codec/attrs/base/shared.rs | 40 + src/stun_codec/attrs/base/unknown.rs | 31 + src/stun_codec/attrs/change_address.rs | 51 + src/stun_codec/attrs/changed_address.rs | 50 + src/stun_codec/attrs/error_code.rs | 62 + src/stun_codec/attrs/fingerprint.rs | 35 + src/stun_codec/attrs/mapped_address.rs | 62 + src/stun_codec/attrs/message_integrity.rs | 35 + src/stun_codec/attrs/mod.rs | 270 ++++ src/stun_codec/attrs/nonce.rs | 37 + .../attrs/opt_xor_mapped_address.rs | 50 + src/stun_codec/attrs/other_address.rs | 50 + src/stun_codec/attrs/password.rs | 37 + src/stun_codec/attrs/realm.rs | 37 + src/stun_codec/attrs/reflected_from.rs | 50 + src/stun_codec/attrs/response_address.rs | 50 + src/stun_codec/attrs/response_origin.rs | 50 + src/stun_codec/attrs/software.rs | 37 + src/stun_codec/attrs/source_address.rs | 50 + src/stun_codec/attrs/unknown_attributes.rs | 58 + src/stun_codec/attrs/username.rs | 37 + src/stun_codec/attrs/xor_mapped_address.rs | 65 + src/stun_codec/enums.rs | 46 + src/stun_codec/message.rs | 136 ++ src/stun_codec/mod.rs | 7 + 34 files changed, 1531 insertions(+), 1812 deletions(-) delete mode 100644 src/stun_client.rs delete mode 100644 src/stun_client_2.rs create mode 100644 src/stun_codec/attrs/alternate_server.rs create mode 100644 src/stun_codec/attrs/base/malformed.rs create mode 100644 src/stun_codec/attrs/base/mod.rs create mode 100644 src/stun_codec/attrs/base/shared.rs create mode 100644 src/stun_codec/attrs/base/unknown.rs create mode 100644 src/stun_codec/attrs/change_address.rs create mode 100644 src/stun_codec/attrs/changed_address.rs create mode 100644 src/stun_codec/attrs/error_code.rs create mode 100644 src/stun_codec/attrs/fingerprint.rs create mode 100644 src/stun_codec/attrs/mapped_address.rs create mode 100644 src/stun_codec/attrs/message_integrity.rs create mode 100644 src/stun_codec/attrs/mod.rs create mode 100644 src/stun_codec/attrs/nonce.rs create mode 100644 src/stun_codec/attrs/opt_xor_mapped_address.rs create mode 100644 src/stun_codec/attrs/other_address.rs create mode 100644 src/stun_codec/attrs/password.rs create mode 100644 src/stun_codec/attrs/realm.rs create mode 100644 src/stun_codec/attrs/reflected_from.rs create mode 100644 src/stun_codec/attrs/response_address.rs create mode 100644 src/stun_codec/attrs/response_origin.rs create mode 100644 src/stun_codec/attrs/software.rs create mode 100644 src/stun_codec/attrs/source_address.rs create mode 100644 src/stun_codec/attrs/unknown_attributes.rs create mode 100644 src/stun_codec/attrs/username.rs create mode 100644 src/stun_codec/attrs/xor_mapped_address.rs create mode 100644 src/stun_codec/enums.rs create mode 100644 src/stun_codec/message.rs create mode 100644 src/stun_codec/mod.rs diff --git a/Cargo.lock b/Cargo.lock index b46529c63..3ddf503a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,7 +15,6 @@ dependencies = [ name = "always-online-stun" version = "0.1.0" dependencies = [ - "bitwise", "futures", "log", "pretty_env_logger", @@ -56,20 +55,6 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" -[[package]] -name = "bitintr" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba5a5c4df8ac8673f22698f443ef1ce3853d7f22d5a15ebf66b9a7553b173dd" - -[[package]] -name = "bitwise" -version = "0.2.0" -dependencies = [ - "bitintr", - "rustc_version", -] - [[package]] name = "build_const" version = "0.2.2" @@ -695,15 +680,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - [[package]] name = "rustls" version = "0.20.4" @@ -741,21 +717,6 @@ dependencies = [ "untrusted", ] -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "serde" version = "1.0.136" diff --git a/Cargo.toml b/Cargo.toml index e0315bdb1..e5a43bddc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,6 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bitwise = { path = "../bitwise", default-features = false } futures = { version = "0.3.17" } log = { version = "0.4.16" } pretty_env_logger = { version = "0.4.0" } diff --git a/src/geoip.rs b/src/geoip.rs index 9e2320e43..0fcf4a345 100644 --- a/src/geoip.rs +++ b/src/geoip.rs @@ -51,12 +51,10 @@ impl IpGeolocationIoClient { .map_err(|err| io::Error::new(ErrorKind::Other, err))?; let lat = response.get("latitude") - .cloned() .map(|lat_str| lat_str.parse().unwrap()) .unwrap_or(0 as f32); let lon = response.get("longitude") - .cloned() .map(|lon_str| lon_str.parse().unwrap()) .unwrap_or(0 as f32); diff --git a/src/main.rs b/src/main.rs index 31b06aa18..e8645d61b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ use crate::utils::join_all_with_semaphore; use crate::outputs::{ValidHosts, ValidIpV4s, ValidIpV6s}; use crate::servers::StunServer; use crate::stun::{StunServerTestResult, StunSocketResponse}; -use crate::stun_client_2::{Attribute, GenericAttrReader, NonParsableAttribute}; +use crate::stun_codec::{Attribute, NonParsableAttribute}; extern crate pretty_env_logger; #[macro_use] extern crate log; @@ -23,8 +23,7 @@ mod utils; mod outputs; mod geoip; mod git; -mod stun_client; -mod stun_client_2; +mod stun_codec; const CONCURRENT_SOCKETS_USED_LIMIT: usize = 64; @@ -45,7 +44,7 @@ async fn get_stun_response(addr: &str) -> io::Result<()> { let bytes_read = bytes_read.unwrap(); - let r = stun_client_2::StunMessageReader { bytes: buf[0..bytes_read].as_ref() }; + let r = stun_codec::StunMessageReader { bytes: buf[0..bytes_read].as_ref() }; info!("Method {:?} , Class {:?}", r.get_method().unwrap(), r.get_class()); r.get_attrs().for_each(|attr| { match &attr { diff --git a/src/stun_client.rs b/src/stun_client.rs deleted file mode 100644 index 403b09f7b..000000000 --- a/src/stun_client.rs +++ /dev/null @@ -1,492 +0,0 @@ -use std::convert::TryInto; -use std::fmt::format; -use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; - -#[derive(Debug)] -enum MessageClass { - Request, - Indirection, - SuccessResponse, - ErrorResponse -} - -#[derive(Debug)] -enum Method { - Binding -} - -struct StunHeaderReader<'a> { - bytes: &'a [u8], -} - -#[derive(Debug)] -enum StunReaderError { - NotEnoughBytes { - expected: usize, - actual: usize, - }, - UnknownMethod { - code: u16 - }, - UnknownAddressFamily { - code: u8 - } -} - -#[derive(PartialEq)] -enum AddressFamily { - Ipv4, - Ipv6, -} - -type StunReaderResult = Result; - -impl StunHeaderReader<'_> { - const HEADER_SIZE: usize = 20; - - fn new(bytes: &[u8]) -> StunReaderResult { - if bytes.len() < StunHeaderReader::HEADER_SIZE { - Err(StunReaderError::NotEnoughBytes { - expected: StunHeaderReader::HEADER_SIZE, - actual: bytes.len(), - }) - } else { - Ok(StunHeaderReader { bytes: &bytes[0..20] }) - } - } - - fn get_message_type(&self) -> u16 { - let msg_type: u16 = u16::from_be_bytes(self.bytes[0..2].try_into().unwrap() ); - msg_type - } - - fn get_class(&self) -> MessageClass { - let msg_type = self.get_message_type(); - let mut class: u16 = 0; - class = bitwise::copy_bit(msg_type, 4u8, class, 0u8); - class = bitwise::copy_bit(msg_type, 8u8, class, 1u8); - match class { - 0 => MessageClass::Request, - 1 => MessageClass::Indirection, - 2 => MessageClass::SuccessResponse, - 3 => MessageClass::ErrorResponse, - _ => panic!("Impossible message class") - } - } - - fn get_method(&self) -> StunReaderResult { - let msg_type = self.get_message_type(); - let method_code: u16 = bitwise::extract_bits(msg_type, 0u8, 4u8) - | bitwise::extract_bits(msg_type, 4u8, 3u8) - | bitwise::extract_bits(msg_type, 9u8, 5u8); - match method_code { - 1 => Ok(Method::Binding), - _ => Err(StunReaderError::UnknownMethod { code: method_code }) - } - } - - fn get_length(&self) -> u16 { - let length: u16 = u16::from_be_bytes(self.bytes[2..4].try_into().unwrap()); - length - } - - fn get_cookie(&self) -> u32 { - let cookie: u32 = u32::from_be_bytes(self.bytes[4..8].try_into().unwrap()); - cookie - } - - fn get_transaction_id(&self) -> (u32, u32, u32) { - let transaction_id = (u32::from_ne_bytes(self.bytes[8..12].try_into().unwrap()), - u32::from_ne_bytes(self.bytes[12..16].try_into().unwrap()), - u32::from_ne_bytes(self.bytes[16..20].try_into().unwrap())); - transaction_id - } - - fn get_used_bytes(&self) -> u16 { - 20 - } - - fn to_string(&self) -> String { - format!("Method: {:?} , Class {:?}\n", self.get_method(), self.get_class()) - } -} - -fn get_attr_length(bytes: &[u8]) -> u16 { - let length = u16::from_be_bytes(bytes[2..4].try_into().unwrap()); - length -} - -fn get_attr_length_padded(bytes: &[u8]) -> u16 { - let length_padded = (get_attr_length(bytes) + 4 - 1) & (-4i16 as u16); // bring attr length to the nearest multiple of 4 to account for padding - length_padded -} - -fn get_attr_type(bytes: &[u8]) -> u16 { - let typ = u16::from_be_bytes(bytes[0..2].try_into().unwrap()); - typ -} - -struct MappedAddressReader<'a> { - bytes: &'a [u8] -} - -impl MappedAddressReader<'_> { - fn supports(bytes: &[u8]) -> bool { - let supports = if bytes.len() < 2 { false } else { get_attr_type(bytes) == 0x0001 }; - supports - } - - fn new(bytes: &[u8]) -> StunReaderResult { - if bytes.len() < 12 { - Err(StunReaderError::NotEnoughBytes { expected: 12, actual: bytes.len() }) - } else { - let reader = MappedAddressReader { bytes }; - if reader.get_family()? == AddressFamily::Ipv6 && bytes.len() < 24 { - Err(StunReaderError::NotEnoughBytes { expected: 24, actual: bytes.len() }) - } else { - Ok(reader) - } - } - } - - fn get_family(&self) -> StunReaderResult { - let family = self.bytes[5]; - match family { - 1 => Ok(AddressFamily::Ipv4), - 2 => Ok(AddressFamily::Ipv6), - _ => Err(StunReaderError::UnknownAddressFamily { code: family }) - } - } - - fn get_port(&self) -> u16 { - let port: u16 = u16::from_be_bytes(self.bytes[6..8].try_into().unwrap()); - port - } - - fn get_addr(&self) -> StunReaderResult { - match self.get_family()? { - AddressFamily::Ipv4 => { - let ip_num= u32::from_be_bytes(self.bytes[8..12].try_into().unwrap()); - Ok(IpAddr::V4(Ipv4Addr::from(ip_num))) - }, - AddressFamily::Ipv6 => { - let ip_num = u128::from_be_bytes(self.bytes[8..24].try_into().unwrap()); - Ok(IpAddr::V6(Ipv6Addr::from(ip_num))) - }, - } - } - - fn get_used_bytes(&self) -> u16 { - let used_bytes = 4 + get_attr_length_padded(self.bytes); - used_bytes - } - - fn to_string(&self) -> String { - format!("MappedAddress {:?}", SocketAddr::new(self.get_addr().unwrap(), self.get_port())) - } -} - -struct AnyAttributeReader<'a> { - bytes: &'a [u8] -} - -impl AnyAttributeReader<'_> { - fn supports(bytes: &[u8]) -> bool { - let supports = if bytes.len() < 2 { false } else { true }; - supports - } - - fn new(bytes: &[u8]) -> StunReaderResult { - if bytes.len() < 2 { - Err(StunReaderError::NotEnoughBytes { expected: 12, actual: bytes.len() }) - } else { - let reader = AnyAttributeReader { bytes }; - Ok(reader) - } - } - - fn get_used_bytes(&self) -> u16 { - let used_bytes = 4 + get_attr_length_padded(self.bytes); - used_bytes - } - - fn to_string(&self) -> String { - format!("AnyAttribute type {:04x} len {} bytes {:?}", get_attr_type(self.bytes), get_attr_length(self.bytes), &self.bytes[4..get_attr_length_padded(self.bytes) as usize] ) - } -} - - -// RFC 5780 -struct ResponseOriginReader<'a> { - bytes: &'a [u8] -} - -impl ResponseOriginReader<'_> { - fn supports(bytes: &[u8]) -> bool { - let supports = if bytes.len() < 2 { false } else { get_attr_type(bytes) == 0x802b }; - supports - } - - fn new(bytes: &[u8]) -> StunReaderResult { - if bytes.len() < 12 { - Err(StunReaderError::NotEnoughBytes { expected: 12, actual: bytes.len() }) - } else { - let reader = ResponseOriginReader { bytes }; - if reader.get_family()? == AddressFamily::Ipv6 && bytes.len() < 24 { - Err(StunReaderError::NotEnoughBytes { expected: 24, actual: bytes.len() }) - } else { - Ok(reader) - } - } - } - - fn get_family(&self) -> StunReaderResult { - let family = self.bytes[5]; - match family { - 1 => Ok(AddressFamily::Ipv4), - 2 => Ok(AddressFamily::Ipv6), - _ => Err(StunReaderError::UnknownAddressFamily { code: family }) - } - } - - fn get_port(&self) -> u16 { - let port: u16 = u16::from_be_bytes(self.bytes[6..8].try_into().unwrap()); - port - } - - fn get_addr(&self) -> StunReaderResult { - match self.get_family()? { - AddressFamily::Ipv4 => { - let octets: [u8; 4] = self.bytes[8..12].try_into().unwrap(); - Ok(IpAddr::V4(Ipv4Addr::from(octets))) - }, - AddressFamily::Ipv6 => { - let octets: [u8; 16] = self.bytes[8..24].try_into().unwrap(); - Ok(IpAddr::V6(Ipv6Addr::from(octets))) - }, - } - } - - fn get_used_bytes(&self) -> u16 { - let used_bytes = 4 + get_attr_length_padded(self.bytes); - used_bytes - } - - fn to_string(&self) -> String { - format!("ResponseOrigin {:?}", SocketAddr::new(self.get_addr().unwrap(), self.get_port())) - } -} - -struct XorMappedAddressReader<'a> { - bytes: &'a [u8], - transaction_id: &'a (u32, u32, u32), -} - -impl XorMappedAddressReader<'_> { - fn supports(bytes: &[u8]) -> bool { - let supports = if bytes.len() < 2 { false } else { get_attr_type(bytes) == 0x0020 }; - supports - } - - fn new<'a>(bytes: &'a [u8], transaction_id: &'a (u32, u32, u32)) -> StunReaderResult> { - if bytes.len() < 12 { - Err(StunReaderError::NotEnoughBytes { expected: 12, actual: bytes.len() }) - } else { - let reader = XorMappedAddressReader { bytes , transaction_id }; - if reader.get_family()? == AddressFamily::Ipv6 && bytes.len() < 24 { - Err(StunReaderError::NotEnoughBytes { expected: 24, actual: bytes.len() }) - } else { - Ok(reader) - } - } - } - - fn get_family(&self) -> StunReaderResult { - let family = self.bytes[5]; - match family { - 1 => Ok(AddressFamily::Ipv4), - 2 => Ok(AddressFamily::Ipv6), - _ => Err(StunReaderError::UnknownAddressFamily { code: family }) - } - } - - fn get_port(&self) -> u16 { - let port: u16 = u16::from_be_bytes(self.bytes[6..8].try_into().unwrap()) ^ 0x2112; // xor with top half of magic cookie - port - } - - fn get_addr(&self) -> StunReaderResult { - match self.get_family()? { - AddressFamily::Ipv4 => { - let ip_num = u32::from_be_bytes(self.bytes[8..12].try_into().unwrap()) ^ 0x2112A442; // xor with magic cookie - Ok(IpAddr::V4(Ipv4Addr::from(ip_num))) - }, - AddressFamily::Ipv6 => { - let t_id = self.transaction_id; - let ip_num = u128::from_be_bytes(self.bytes[8..24].try_into().unwrap()) ^ (0x2112A442_u128 << 92 | (t_id.2 as u128) << 64 | (t_id.1 as u128) << 32 | t_id.0 as u128); - Ok(IpAddr::V6(Ipv6Addr::from(ip_num))) - }, - } - } - - fn get_used_bytes(&self) -> u16 { - let used_bytes = 4 + get_attr_length_padded(self.bytes); - used_bytes - } - - fn to_string(&self) -> String { - format!("XorMappedAddress {:?}", SocketAddr::new(self.get_addr().unwrap(), self.get_port())) - } -} - -struct ComprehensionOptionalXorMappedAddressReader<'a> { - bytes: &'a [u8], - transaction_id: &'a (u32, u32, u32), -} - -impl ComprehensionOptionalXorMappedAddressReader<'_> { - fn supports(bytes: &[u8]) -> bool { - let supports = if bytes.len() < 2 { false } else { get_attr_type(bytes) == 0x8020 }; - supports - } - - fn new<'a>(bytes: &'a [u8], transaction_id: &'a (u32, u32, u32)) -> StunReaderResult> { - if bytes.len() < 12 { - Err(StunReaderError::NotEnoughBytes { expected: 12, actual: bytes.len() }) - } else { - let reader = ComprehensionOptionalXorMappedAddressReader { bytes , transaction_id }; - if reader.get_family()? == AddressFamily::Ipv6 && bytes.len() < 24 { - Err(StunReaderError::NotEnoughBytes { expected: 24, actual: bytes.len() }) - } else { - Ok(reader) - } - } - } - - fn get_family(&self) -> StunReaderResult { - let family = self.bytes[5]; - match family { - 1 => Ok(AddressFamily::Ipv4), - 2 => Ok(AddressFamily::Ipv6), - _ => Err(StunReaderError::UnknownAddressFamily { code: family }) - } - } - - fn get_port(&self) -> u16 { - let port: u16 = u16::from_be_bytes(self.bytes[6..8].try_into().unwrap()) ^ 0x2112; // xor with top half of magic cookie - port - } - - fn get_addr(&self) -> StunReaderResult { - match self.get_family()? { - AddressFamily::Ipv4 => { - let ip_num = u32::from_be_bytes(self.bytes[8..12].try_into().unwrap()) ^ 0x2112A442; // xor with magic cookie - Ok(IpAddr::V4(Ipv4Addr::from(ip_num))) - }, - AddressFamily::Ipv6 => { - let t_id = self.transaction_id; - let ip_num = u128::from_be_bytes(self.bytes[8..24].try_into().unwrap()) ^ (0x2112A442_u128 << 92 | (t_id.2 as u128) << 64 | (t_id.1 as u128) << 32 | t_id.0 as u128); - Ok(IpAddr::V6(Ipv6Addr::from(ip_num))) - }, - } - } - - fn get_used_bytes(&self) -> u16 { - let used_bytes = 4 + get_attr_length_padded(self.bytes); - used_bytes - } - - fn to_string(&self) -> String { - format!("ComprehensionOptionalXorMappedAddress {:?}", SocketAddr::new(self.get_addr().unwrap(), self.get_port())) - } -} - -enum RfcSpec { - Rfc3489, - Rfc5245, - Rfc5389, - Rfc5766, - Rfc5780 -} - -enum MessageAttribute { - Reserved0x0000, - MappedAddress, - ResponseAddress, - ChangeAddress, - SourceAddress, - ChangedAddress, - Username, - Password, - MessageIntegrity, - ErrorCode, - UnknownAttribute, - ReflectedFrom, - Realm, - Nonce, - XorMappedAddress, - OptXorMappedAddress, - Software, - AlternateServer, - Fingerprint -} - -impl MessageAttribute { - fn get_code(&self) -> u16 { - match self { - MessageAttribute::Reserved0x0000 => { 0x0000 } - MessageAttribute::MappedAddress => { 0x0001 } - MessageAttribute::ResponseAddress => { 0x0002 } - MessageAttribute::ChangeAddress => { 0x0003 } - MessageAttribute::SourceAddress => { 0x0004 } - MessageAttribute::ChangedAddress => { 0x0005 } - MessageAttribute::Username => { 0x0006 } - MessageAttribute::Password => { 0x0007 } - MessageAttribute::MessageIntegrity => { 0x0008 } - MessageAttribute::ErrorCode => { 0x0009 } - MessageAttribute::UnknownAttribute => { 0x000A } - MessageAttribute::ReflectedFrom => { 0x000B } - MessageAttribute::Realm => { 0x0014 } - MessageAttribute::Nonce => { 0x0015 } - MessageAttribute::XorMappedAddress => { 0x0020 } - MessageAttribute::OptXorMappedAddress => { 0x8020 } - MessageAttribute::Software => { 0x8022 } - MessageAttribute::AlternateServer => { 0x8023 } - MessageAttribute::Fingerprint => { 0x8028 } - } - } -} - -pub(crate) fn read_stun_message(bytes: &[u8]) { - - let r = StunHeaderReader::new(bytes).unwrap(); - println!("{}", r.to_string()); - let mut bytes = &bytes[r.get_used_bytes() as usize ..]; - let t_id = r.get_transaction_id(); - loop { - if MappedAddressReader::supports(bytes) { - let r = MappedAddressReader::new(bytes).unwrap(); - println!("{}", r.to_string()); - bytes = &bytes[r.get_used_bytes() as usize ..]; - } else if XorMappedAddressReader::supports(bytes) { - let r = XorMappedAddressReader::new(bytes, &t_id).unwrap(); - println!("{}", r.to_string()); - bytes = &bytes[r.get_used_bytes() as usize ..]; - } else if ResponseOriginReader::supports(bytes) { - let r = ResponseOriginReader::new(bytes).unwrap(); - println!("{}", r.to_string()); - bytes = &bytes[r.get_used_bytes() as usize ..]; - } else if ComprehensionOptionalXorMappedAddressReader::supports(bytes) { - let r = ComprehensionOptionalXorMappedAddressReader::new(bytes, &t_id).unwrap(); - println!("{}", r.to_string()); - bytes = &bytes[r.get_used_bytes() as usize ..]; - } else if AnyAttributeReader::supports(bytes) { - let r = AnyAttributeReader::new(bytes).unwrap(); - println!("{}", r.to_string()); - bytes = &bytes[r.get_used_bytes() as usize ..]; - } else { - println!("Bytes left {}", bytes.len()); - break; - } - } -} diff --git a/src/stun_client_2.rs b/src/stun_client_2.rs deleted file mode 100644 index ed7564fe1..000000000 --- a/src/stun_client_2.rs +++ /dev/null @@ -1,1274 +0,0 @@ -use std::cmp::min; -use std::convert::TryInto; -use std::io::ErrorKind::Other; -use std::mem; -use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; -use std::str; -use std::str::Utf8Error; - -#[derive(Debug)] -pub enum MessageClass { - Request, - Indirection, - SuccessResponse, - ErrorResponse, -} - -#[derive(Debug)] -pub enum Method { - Binding -} - -pub enum ComprehensionCategory { - Required, - Optional, -} - -pub struct MalformedAttrReader<'a> { - bytes: &'a [u8], -} - -impl MalformedAttrReader<'_> { - pub fn get_type_raw(&self) -> u16 { - match self.bytes.len() { - 0 => 0, - 1 => u8::from_be(self.bytes[0]) as u16, - _ => u16::from_be_bytes(self.bytes[0..2].try_into().unwrap()), - } - } - - pub fn get_value_length_raw(&self) -> u16 { - match self.bytes.len() { - 0 | 1 | 2 | 3 | 4 => 0, - _ => u16::from_be_bytes(self.bytes[2..4].try_into().unwrap()), - } - } - - pub fn get_value_raw(&self) -> &[u8] { - match self.bytes.len() { - 0 | 1 | 2 | 3 | 4 => &self.bytes[0..0], - _ => { - let length_raw = self.get_value_length_raw() as usize; - let target_value_size = min(length_raw, self.bytes.len() - 4) / 4; - &self.bytes[5..target_value_size] - } - } - } -} - -pub struct UnknownAttrReader<'a> { - bytes: &'a [u8], -} - -impl UnknownAttrReader<'_> { - pub fn get_value_raw(&self) -> &[u8] { - &self.bytes[4..(self.get_value_length() as usize)] - } - - pub fn get_type_raw(&self) -> u16 { - u16::from_be_bytes(self.bytes[0..2].try_into().unwrap()) - } - - pub fn get_comprehension_category(&self) -> ComprehensionCategory { - let typ = self.get_type_raw(); - if typ <= 0x7FFF { ComprehensionCategory::Required } else { ComprehensionCategory::Optional } - } - - pub fn get_value_length(&self) -> u16 { - u16::from_be_bytes(self.bytes[2..4].try_into().unwrap()) - } - - pub fn get_total_length(&self) -> u16 { 4 + ((self.get_value_length() + 4 - 1) & (-4i16 as u16)) } -} - -pub enum RfcSpec { - Rfc3489, - Rfc5245, - Rfc5389, - Rfc5766, - Rfc5780, -} - -#[derive(PartialEq)] -pub enum AddressFamily { - V4, - V6, -} - -pub trait GenericAttrReader { - fn get_bytes(&self) -> &[u8]; - - fn get_value_raw(&self) -> &[u8] { - &self.get_bytes()[4..(self.get_value_length() as usize)] - } - - fn get_type_raw(&self) -> u16 { - u16::from_be_bytes(self.get_bytes()[0..2].try_into().unwrap()) - } - - fn get_value_length(&self) -> u16 { - u16::from_be_bytes(self.get_bytes()[2..4].try_into().unwrap()) - } - - fn get_total_length(&self) -> u16 { - 4 + ((self.get_value_length() + 4 - 1) & (-4i16 as u16)) - } - - fn get_rfc_spec(&self) -> RfcSpec; - - fn get_comprehension_category(&self) -> ComprehensionCategory { - let typ = self.get_type_raw(); - if typ <= 0x7FFF { ComprehensionCategory::Required } else { ComprehensionCategory::Optional } - } - - fn check_compliance(&self) -> Vec; - - fn is_deprecated(&self) -> bool; -} - -pub struct MappedAddressAttributeReader<'a> { - bytes: &'a [u8], -} - -impl MappedAddressAttributeReader<'_> { - pub fn get_address_family(&self) -> Result { - let family_code = self.get_address_family_raw(); - match family_code { - 1 => Ok(AddressFamily::V4), - 2 => Ok(AddressFamily::V6), - _ => Err(family_code) - } - } - - pub fn get_address_family_raw(&self) -> u8 { - self.bytes[5] - } - - pub fn get_port(&self) -> u16 { - u16::from_be_bytes(self.bytes[6..8].try_into().unwrap()) - } - - pub fn get_address(&self) -> Result { - match self.get_address_family()? { - AddressFamily::V4 => { - let ip_num = u32::from_be_bytes(self.bytes[8..12].try_into().unwrap()); - Ok(IpAddr::V4(Ipv4Addr::from(ip_num))) - } - AddressFamily::V6 => { - let ip_num = u128::from_be_bytes(self.bytes[8..24].try_into().unwrap()); - Ok(IpAddr::V6(Ipv6Addr::from(ip_num))) - } - } - } -} - -impl GenericAttrReader for MappedAddressAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.bytes - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc3489 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - false - } -} - -pub struct ResponseOriginAttributeReader<'a> { - mapped_address_reader: MappedAddressAttributeReader<'a>, -} - -impl ResponseOriginAttributeReader<'_> { - pub fn get_address_family(&self) -> Result { - self.mapped_address_reader.get_address_family() - } - - pub fn get_address_family_raw(&self) -> u8 { - self.mapped_address_reader.get_address_family_raw() - } - - pub fn get_port(&self) -> u16 { - self.mapped_address_reader.get_port() - } - - pub fn get_address(&self) -> Result { - self.mapped_address_reader.get_address() - } -} - -impl GenericAttrReader for ResponseOriginAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.mapped_address_reader.get_bytes() - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc5389 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - false - } -} - -pub struct AlternateServerAttributeReader<'a> { - mapped_address_reader: MappedAddressAttributeReader<'a>, -} - -impl AlternateServerAttributeReader<'_> { - pub fn get_address_family(&self) -> Result { - self.mapped_address_reader.get_address_family() - } - - pub fn get_address_family_raw(&self) -> u8 { - self.mapped_address_reader.get_address_family_raw() - } - - pub fn get_port(&self) -> u16 { - self.mapped_address_reader.get_port() - } - - pub fn get_address(&self) -> Result { - self.mapped_address_reader.get_address() - } -} - -impl GenericAttrReader for AlternateServerAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.mapped_address_reader.get_bytes() - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc5389 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - false - } -} - -pub struct OtherAddressAttributeReader<'a> { - mapped_address_reader: MappedAddressAttributeReader<'a>, -} - -impl OtherAddressAttributeReader<'_> { - pub fn get_address_family(&self) -> Result { - self.mapped_address_reader.get_address_family() - } - - pub fn get_address_family_raw(&self) -> u8 { - self.mapped_address_reader.get_address_family_raw() - } - - pub fn get_port(&self) -> u16 { - self.mapped_address_reader.get_port() - } - - pub fn get_address(&self) -> Result { - self.mapped_address_reader.get_address() - } -} - -impl GenericAttrReader for OtherAddressAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.mapped_address_reader.get_bytes() - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc5389 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - false - } -} - -pub struct XorMappedAddressAttributeReader<'a> { - bytes: &'a [u8], - transaction_id: &'a [u8; 12], -} - -impl XorMappedAddressAttributeReader<'_> { - pub fn get_address_family(&self) -> Result { - let family_code = self.get_address_family_raw(); - match family_code { - 1 => Ok(AddressFamily::V4), - 2 => Ok(AddressFamily::V6), - _ => Err(family_code) - } - } - - pub fn get_address_family_raw(&self) -> u8 { - self.bytes[5] - } - - pub fn get_port(&self) -> u16 { - u16::from_be_bytes(self.bytes[6..8].try_into().unwrap()) ^ 0x2112 // xor with top half of magic cookie - } - - pub fn get_address(&self) -> Result { - match self.get_address_family()? { - AddressFamily::V4 => { - let ip_num = u32::from_be_bytes(self.bytes[8..12].try_into().unwrap()) ^ 0x2112A442; // xor with magic cookie - Ok(IpAddr::V4(Ipv4Addr::from(ip_num))) - } - AddressFamily::V6 => { - let t_id = self.transaction_id; - let xor_mask = 0x2112A442_u128 << 92 | u128::from(u64::from_ne_bytes(t_id[4..12].try_into().unwrap())) << 64 | u32::from_ne_bytes(t_id[0..4].try_into().unwrap()) as u128; - let ip_num = u128::from_be_bytes(self.bytes[8..24].try_into().unwrap()) ^ xor_mask; - Ok(IpAddr::V6(Ipv6Addr::from(ip_num))) - } - } - } -} - -impl GenericAttrReader for XorMappedAddressAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.bytes - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc5389 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - false - } -} - -pub struct OptXorMappedAddressAttributeReader<'a> { - xor_mapped_address_reader: XorMappedAddressAttributeReader<'a>, -} - -impl OptXorMappedAddressAttributeReader<'_> { - pub fn get_address_family(&self) -> Result { - self.xor_mapped_address_reader.get_address_family() - } - - pub fn get_address_family_raw(&self) -> u8 { - self.xor_mapped_address_reader.get_address_family_raw() - } - - pub fn get_port(&self) -> u16 { - self.xor_mapped_address_reader.get_port() - } - - pub fn get_address(&self) -> Result { - self.xor_mapped_address_reader.get_address() - } -} - -impl GenericAttrReader for OptXorMappedAddressAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.xor_mapped_address_reader.get_bytes() - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc3489 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - true - } -} - -pub struct ResponseAddressAttributeReader<'a> { - mapped_address_reader: MappedAddressAttributeReader<'a>, -} - -impl ResponseAddressAttributeReader<'_> { - pub fn get_address_family(&self) -> Result { - self.mapped_address_reader.get_address_family() - } - - pub fn get_address_family_raw(&self) -> u8 { - self.mapped_address_reader.get_address_family_raw() - } - - pub fn get_port(&self) -> u16 { - self.mapped_address_reader.get_port() - } - - pub fn get_address(&self) -> Result { - self.mapped_address_reader.get_address() - } -} - -impl GenericAttrReader for ResponseAddressAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.mapped_address_reader.get_bytes() - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc3489 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - true - } -} - -pub struct ChangeAddressAttributeReader<'a> { - mapped_address_reader: MappedAddressAttributeReader<'a>, -} - -impl ChangeAddressAttributeReader<'_> { - pub fn get_address_family(&self) -> Result { - self.mapped_address_reader.get_address_family() - } - - pub fn get_address_family_raw(&self) -> u8 { - self.mapped_address_reader.get_address_family_raw() - } - - pub fn get_port(&self) -> u16 { - self.mapped_address_reader.get_port() - } - - pub fn get_address(&self) -> Result { - self.mapped_address_reader.get_address() - } -} - -impl GenericAttrReader for ChangeAddressAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.mapped_address_reader.get_bytes() - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc3489 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - true - } -} - -pub struct SourceAddressAttributeReader<'a> { - mapped_address_reader: MappedAddressAttributeReader<'a>, -} - -impl SourceAddressAttributeReader<'_> { - pub fn get_address_family(&self) -> Result { - self.mapped_address_reader.get_address_family() - } - - pub fn get_address_family_raw(&self) -> u8 { - self.mapped_address_reader.get_address_family_raw() - } - - pub fn get_port(&self) -> u16 { - self.mapped_address_reader.get_port() - } - - pub fn get_address(&self) -> Result { - self.mapped_address_reader.get_address() - } -} - -impl GenericAttrReader for SourceAddressAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.mapped_address_reader.get_bytes() - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc3489 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - true - } -} - -pub struct ChangedAddressAttributeReader<'a> { - mapped_address_reader: MappedAddressAttributeReader<'a>, -} - -impl ChangedAddressAttributeReader<'_> { - pub fn get_address_family(&self) -> Result { - self.mapped_address_reader.get_address_family() - } - - pub fn get_address_family_raw(&self) -> u8 { - self.mapped_address_reader.get_address_family_raw() - } - - pub fn get_port(&self) -> u16 { - self.mapped_address_reader.get_port() - } - - pub fn get_address(&self) -> Result { - self.mapped_address_reader.get_address() - } -} - -impl GenericAttrReader for ChangedAddressAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.mapped_address_reader.get_bytes() - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc3489 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - true - } -} - -pub struct ReflectedFromAttributeReader<'a> { - mapped_address_reader: MappedAddressAttributeReader<'a>, -} - -impl ReflectedFromAttributeReader<'_> { - pub fn get_address_family(&self) -> Result { - self.mapped_address_reader.get_address_family() - } - - pub fn get_address_family_raw(&self) -> u8 { - self.mapped_address_reader.get_address_family_raw() - } - - pub fn get_port(&self) -> u16 { - self.mapped_address_reader.get_port() - } - - pub fn get_address(&self) -> Result { - self.mapped_address_reader.get_address() - } -} - -impl GenericAttrReader for ReflectedFromAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.mapped_address_reader.get_bytes() - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc3489 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - true - } -} - -pub struct UsernameAttributeReader<'a> { - bytes: &'a [u8], -} - -impl UsernameAttributeReader<'_> { - pub fn get_username(&self) -> Result<&str, Utf8Error> { - str::from_utf8(&self.bytes[2..2 + self.get_value_length() as usize]) - } -} - -impl GenericAttrReader for UsernameAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.bytes - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc3489 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - false - } -} - -pub struct PasswordAttributeReader<'a> { - bytes: &'a [u8], -} - -impl PasswordAttributeReader<'_> { - pub fn get_password(&self) -> Result<&str, Utf8Error> { - str::from_utf8(&self.bytes[2..2 + self.get_value_length() as usize]) - } -} - -impl GenericAttrReader for PasswordAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.bytes - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc3489 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - true - } -} - -pub struct RealmAttributeReader<'a> { - bytes: &'a [u8], -} - -impl RealmAttributeReader<'_> { - pub fn get_realm(&self) -> Result<&str, Utf8Error> { - str::from_utf8(&self.bytes[2..2 + self.get_value_length() as usize]) - } -} - -impl GenericAttrReader for RealmAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.bytes - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc3489 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - false - } -} - -pub struct NonceAttributeReader<'a> { - bytes: &'a [u8], -} - -impl NonceAttributeReader<'_> { - pub fn get_nonce(&self) -> Result<&str, Utf8Error> { - str::from_utf8(&self.bytes[2..2 + self.get_value_length() as usize]) - } -} - -impl GenericAttrReader for NonceAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.bytes - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc3489 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - false - } -} - -pub struct UnknownAttributesAttributeReader<'a> { - bytes: &'a [u8], -} - -pub struct UnknownAttrIter<'a> { - bytes: &'a [u8], - offset: usize, -} - -impl Iterator for UnknownAttrIter<'_> { - type Item = u16; - - fn next(&mut self) -> Option { - if self.offset == self.bytes.len() { - None - } else { - let attr = u16::from_be_bytes(self.bytes[self.offset..self.offset + 2].try_into().unwrap()); - self.offset += 2; - Some(attr) - } - } -} - -impl UnknownAttributesAttributeReader<'_> { - pub fn get_attr_codes(&self) -> UnknownAttrIter { - UnknownAttrIter { - bytes: &self.bytes[2..2+self.get_value_length() as usize], - offset: 0 - } - } -} - -impl GenericAttrReader for UnknownAttributesAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.bytes - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc3489 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - false - } -} - -pub struct MessageIntegrityAttributeReader<'a> { - bytes: &'a [u8], -} - -impl MessageIntegrityAttributeReader<'_> { - pub fn get_digest(&self) -> &[u8; 20] { - self.bytes[2..2 + self.get_value_length() as usize].try_into().unwrap() - } -} - -impl GenericAttrReader for MessageIntegrityAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.bytes - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc5389 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - true - } -} - -pub struct FingerprintAttributeReader<'a> { - bytes: &'a [u8], -} - -impl FingerprintAttributeReader<'_> { - pub fn get_checksum(&self) -> u32 { - u32::from_be_bytes(self.bytes[2..2 + self.get_value_length() as usize].try_into().unwrap()) ^ 0x5354554E - } -} - -impl GenericAttrReader for FingerprintAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.bytes - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc5389 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - true - } -} - -pub struct ErrorCodeAttributeReader<'a> { - bytes: &'a [u8], -} - -#[derive(Debug)] -pub enum ErrorCode { - TryAlternate, - BadRequest, - Unauthorized, - UnknownAttribute, - StaleNonce, - InternalServerError, -} - -impl ErrorCodeAttributeReader<'_> { - pub fn get_error(&self) -> Result { - let error_code = self.get_error_code_raw(); - match error_code { - 300 => Ok(ErrorCode::TryAlternate), - 400 => Ok(ErrorCode::BadRequest), - 401 => Ok(ErrorCode::Unauthorized), - 420 => Ok(ErrorCode::UnknownAttribute), - 438 => Ok(ErrorCode::StaleNonce), - 500 => Ok(ErrorCode::InternalServerError), - _ => Err(error_code) - } - } - - pub fn get_reason(&self) -> Result<&str, Utf8Error> { - str::from_utf8(&self.bytes[4..(4 + self.get_value_length() - 2) as usize]) - } - - pub fn get_error_code_raw(&self) -> u16 { - self.get_class() as u16 * 100 + self.get_number() as u16 - } - - pub fn get_class(&self) -> u8 { - self.bytes[5] >> 5 - } - - pub fn get_number(&self) -> u8 { - self.bytes[6] - } -} - -impl GenericAttrReader for ErrorCodeAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.bytes - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc5389 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - true - } -} - -pub struct SoftwareAttributeReader<'a> { - bytes: &'a [u8], -} - -impl SoftwareAttributeReader<'_> { - pub fn get_software(&self) -> Result<&str, Utf8Error> { - str::from_utf8(&self.bytes[2..2 + self.get_value_length() as usize]) - } -} - -impl GenericAttrReader for SoftwareAttributeReader<'_> { - fn get_bytes(&self) -> &[u8] { - self.bytes - } - - fn get_rfc_spec(&self) -> RfcSpec { - RfcSpec::Rfc5389 - } - - fn check_compliance(&self) -> Vec { - todo!() - } - - fn is_deprecated(&self) -> bool { - false - } -} - -pub enum Attribute<'a> { - MappedAddress(MappedAddressAttributeReader<'a>), - ReflectedFrom(ReflectedFromAttributeReader<'a>), - ResponseAddress(ResponseAddressAttributeReader<'a>), - ChangeAddress(ChangeAddressAttributeReader<'a>), - SourceAddress(SourceAddressAttributeReader<'a>), - ChangedAddress(ChangedAddressAttributeReader<'a>), - XorMappedAddress(XorMappedAddressAttributeReader<'a>), - OptXorMappedAddress(OptXorMappedAddressAttributeReader<'a>), - OtherAddress(OtherAddressAttributeReader<'a>), - ResponseOrigin(ResponseOriginAttributeReader<'a>), - Username(UsernameAttributeReader<'a>), - Password(PasswordAttributeReader<'a>), - MessageIntegrity(MessageIntegrityAttributeReader<'a>), - Fingerprint(FingerprintAttributeReader<'a>), - ErrorCode(ErrorCodeAttributeReader<'a>), - Realm(RealmAttributeReader<'a>), - Nonce(NonceAttributeReader<'a>), - UnknownAttributes(UnknownAttributesAttributeReader<'a>), - Software(SoftwareAttributeReader<'a>), - AlternateServer(AlternateServerAttributeReader<'a>), -} - -impl GenericAttrReader for Attribute<'_> { - fn get_bytes(&self) -> &[u8] { - match self { - Attribute::MappedAddress(r) => r.get_bytes(), - Attribute::ResponseAddress(r) => r.get_bytes(), - Attribute::ChangeAddress(r) => r.get_bytes(), - Attribute::SourceAddress(r) => r.get_bytes(), - Attribute::ChangedAddress(r) => r.get_bytes(), - Attribute::XorMappedAddress(r) => r.get_bytes(), - Attribute::OptXorMappedAddress(r) => r.get_bytes(), - Attribute::OtherAddress(r) => r.get_bytes(), - Attribute::ResponseOrigin(r) => r.get_bytes(), - Attribute::Username(r) => r.get_bytes(), - Attribute::Password(r) => r.get_bytes(), - Attribute::MessageIntegrity(r) => r.get_bytes(), - Attribute::Fingerprint(r) => r.get_bytes(), - Attribute::ErrorCode(r) => r.get_bytes(), - Attribute::Realm(r) => r.get_bytes(), - Attribute::Nonce(r) => r.get_bytes(), - Attribute::UnknownAttributes(r) => r.get_bytes(), - Attribute::ReflectedFrom(r) => r.get_bytes(), - Attribute::Software(r) => r.get_bytes(), - Attribute::AlternateServer(r) => r.get_bytes(), - } - } - - fn get_value_raw(&self) -> &[u8] { - match self { - Attribute::MappedAddress(r) => r.get_value_raw(), - Attribute::ResponseAddress(r) => r.get_value_raw(), - Attribute::ChangeAddress(r) => r.get_value_raw(), - Attribute::SourceAddress(r) => r.get_value_raw(), - Attribute::ChangedAddress(r) => r.get_value_raw(), - Attribute::XorMappedAddress(r) => r.get_value_raw(), - Attribute::OptXorMappedAddress(r) => r.get_value_raw(), - Attribute::OtherAddress(r) => r.get_value_raw(), - Attribute::ResponseOrigin(r) => r.get_value_raw(), - Attribute::Username(r) => r.get_value_raw(), - Attribute::Password(r) => r.get_value_raw(), - Attribute::MessageIntegrity(r) => r.get_value_raw(), - Attribute::Fingerprint(r) => r.get_value_raw(), - Attribute::ErrorCode(r) => r.get_value_raw(), - Attribute::Realm(r) => r.get_value_raw(), - Attribute::Nonce(r) => r.get_value_raw(), - Attribute::UnknownAttributes(r) => r.get_value_raw(), - Attribute::ReflectedFrom(r) => r.get_value_raw(), - Attribute::Software(r) => r.get_value_raw(), - Attribute::AlternateServer(r) => r.get_value_raw(), - } - } - - fn get_type_raw(&self) -> u16 { - match self { - Attribute::MappedAddress(r) => r.get_type_raw(), - Attribute::ResponseAddress(r) => r.get_type_raw(), - Attribute::ChangeAddress(r) => r.get_type_raw(), - Attribute::SourceAddress(r) => r.get_type_raw(), - Attribute::ChangedAddress(r) => r.get_type_raw(), - Attribute::XorMappedAddress(r) => r.get_type_raw(), - Attribute::OptXorMappedAddress(r) => r.get_type_raw(), - Attribute::OtherAddress(r) => r.get_type_raw(), - Attribute::ResponseOrigin(r) => r.get_type_raw(), - Attribute::Username(r) => r.get_type_raw(), - Attribute::Password(r) => r.get_type_raw(), - Attribute::MessageIntegrity(r) => r.get_type_raw(), - Attribute::Fingerprint(r) => r.get_type_raw(), - Attribute::ErrorCode(r) => r.get_type_raw(), - Attribute::Realm(r) => r.get_type_raw(), - Attribute::Nonce(r) => r.get_type_raw(), - Attribute::UnknownAttributes(r) => r.get_type_raw(), - Attribute::ReflectedFrom(r) => r.get_type_raw(), - Attribute::Software(r) => r.get_type_raw(), - Attribute::AlternateServer(r) => r.get_type_raw(), - } - } - - fn get_value_length(&self) -> u16 { - match self { - Attribute::MappedAddress(r) => r.get_value_length(), - Attribute::ResponseAddress(r) => r.get_value_length(), - Attribute::ChangeAddress(r) => r.get_value_length(), - Attribute::SourceAddress(r) => r.get_value_length(), - Attribute::ChangedAddress(r) => r.get_value_length(), - Attribute::XorMappedAddress(r) => r.get_value_length(), - Attribute::OptXorMappedAddress(r) => r.get_value_length(), - Attribute::OtherAddress(r) => r.get_value_length(), - Attribute::ResponseOrigin(r) => r.get_value_length(), - Attribute::Username(r) => r.get_value_length(), - Attribute::Password(r) => r.get_value_length(), - Attribute::MessageIntegrity(r) => r.get_value_length(), - Attribute::Fingerprint(r) => r.get_value_length(), - Attribute::ErrorCode(r) => r.get_value_length(), - Attribute::Realm(r) => r.get_value_length(), - Attribute::Nonce(r) => r.get_value_length(), - Attribute::UnknownAttributes(r) => r.get_value_length(), - Attribute::ReflectedFrom(r) => r.get_value_length(), - Attribute::Software(r) => r.get_value_length(), - Attribute::AlternateServer(r) => r.get_value_length(), - } - } - - fn get_total_length(&self) -> u16 { - match self { - Attribute::MappedAddress(r) => r.get_total_length(), - Attribute::ResponseAddress(r) => r.get_total_length(), - Attribute::ChangeAddress(r) => r.get_total_length(), - Attribute::SourceAddress(r) => r.get_total_length(), - Attribute::ChangedAddress(r) => r.get_total_length(), - Attribute::XorMappedAddress(r) => r.get_total_length(), - Attribute::OptXorMappedAddress(r) => r.get_total_length(), - Attribute::OtherAddress(r) => r.get_total_length(), - Attribute::ResponseOrigin(r) => r.get_total_length(), - Attribute::Username(r) => r.get_total_length(), - Attribute::Password(r) => r.get_total_length(), - Attribute::MessageIntegrity(r) => r.get_total_length(), - Attribute::Fingerprint(r) => r.get_total_length(), - Attribute::ErrorCode(r) => r.get_total_length(), - Attribute::Realm(r) => r.get_total_length(), - Attribute::Nonce(r) => r.get_total_length(), - Attribute::UnknownAttributes(r) => r.get_total_length(), - Attribute::ReflectedFrom(r) => r.get_total_length(), - Attribute::Software(r) => r.get_total_length(), - Attribute::AlternateServer(r) => r.get_total_length(), - } - } - - fn get_rfc_spec(&self) -> RfcSpec { - match self { - Attribute::MappedAddress(r) => r.get_rfc_spec(), - Attribute::ResponseAddress(r) => r.get_rfc_spec(), - Attribute::ChangeAddress(r) => r.get_rfc_spec(), - Attribute::SourceAddress(r) => r.get_rfc_spec(), - Attribute::ChangedAddress(r) => r.get_rfc_spec(), - Attribute::XorMappedAddress(r) => r.get_rfc_spec(), - Attribute::OptXorMappedAddress(r) => r.get_rfc_spec(), - Attribute::OtherAddress(r) => r.get_rfc_spec(), - Attribute::ResponseOrigin(r) => r.get_rfc_spec(), - Attribute::Username(r) => r.get_rfc_spec(), - Attribute::Password(r) => r.get_rfc_spec(), - Attribute::MessageIntegrity(r) => r.get_rfc_spec(), - Attribute::Fingerprint(r) => r.get_rfc_spec(), - Attribute::ErrorCode(r) => r.get_rfc_spec(), - Attribute::Realm(r) => r.get_rfc_spec(), - Attribute::Nonce(r) => r.get_rfc_spec(), - Attribute::UnknownAttributes(r) => r.get_rfc_spec(), - Attribute::ReflectedFrom(r) => r.get_rfc_spec(), - Attribute::Software(r) => r.get_rfc_spec(), - Attribute::AlternateServer(r) => r.get_rfc_spec(), - } - } - - fn check_compliance(&self) -> Vec { - match self { - Attribute::MappedAddress(r) => r.check_compliance(), - Attribute::ResponseAddress(r) => r.check_compliance(), - Attribute::ChangeAddress(r) => r.check_compliance(), - Attribute::SourceAddress(r) => r.check_compliance(), - Attribute::ChangedAddress(r) => r.check_compliance(), - Attribute::XorMappedAddress(r) => r.check_compliance(), - Attribute::OptXorMappedAddress(r) => r.check_compliance(), - Attribute::OtherAddress(r) => r.check_compliance(), - Attribute::ResponseOrigin(r) => r.check_compliance(), - Attribute::Username(r) => r.check_compliance(), - Attribute::Password(r) => r.check_compliance(), - Attribute::MessageIntegrity(r) => r.check_compliance(), - Attribute::Fingerprint(r) => r.check_compliance(), - Attribute::ErrorCode(r) => r.check_compliance(), - Attribute::Realm(r) => r.check_compliance(), - Attribute::Nonce(r) => r.check_compliance(), - Attribute::UnknownAttributes(r) => r.check_compliance(), - Attribute::ReflectedFrom(r) => r.check_compliance(), - Attribute::Software(r) => r.check_compliance(), - Attribute::AlternateServer(r) => r.check_compliance(), - } - } - - fn is_deprecated(&self) -> bool { - match self { - Attribute::MappedAddress(r) => r.is_deprecated(), - Attribute::ResponseAddress(r) => r.is_deprecated(), - Attribute::ChangeAddress(r) => r.is_deprecated(), - Attribute::SourceAddress(r) => r.is_deprecated(), - Attribute::ChangedAddress(r) => r.is_deprecated(), - Attribute::XorMappedAddress(r) => r.is_deprecated(), - Attribute::OptXorMappedAddress(r) => r.is_deprecated(), - Attribute::OtherAddress(r) => r.is_deprecated(), - Attribute::ResponseOrigin(r) => r.is_deprecated(), - Attribute::Username(r) => r.is_deprecated(), - Attribute::Password(r) => r.is_deprecated(), - Attribute::MessageIntegrity(r) => r.is_deprecated(), - Attribute::Fingerprint(r) => r.is_deprecated(), - Attribute::ErrorCode(r) => r.is_deprecated(), - Attribute::Realm(r) => r.is_deprecated(), - Attribute::Nonce(r) => r.is_deprecated(), - Attribute::UnknownAttributes(r) => r.is_deprecated(), - Attribute::ReflectedFrom(r) => r.is_deprecated(), - Attribute::Software(r) => r.is_deprecated(), - Attribute::AlternateServer(r) => r.is_deprecated(), - } - } -} - -pub enum NonParsableAttribute<'a> { - Unknown(UnknownAttrReader<'a>), - Malformed(MalformedAttrReader<'a>), -} - -pub struct Iter<'a> { - attr_bytes: &'a [u8], - curr_offset: usize, - transaction_id: &'a [u8; 12], -} - -impl<'a> Iterator for Iter<'a> { - type Item = Result, NonParsableAttribute<'a>>; - - fn next(&mut self) -> Option { - if self.attr_bytes.len() - self.curr_offset == 0 { return None; } - - let bytes = &self.attr_bytes[self.curr_offset..self.attr_bytes.len()]; - - if self.attr_bytes.len() - self.curr_offset <= 4 { - let item = Some( - Err( - NonParsableAttribute::Malformed( - MalformedAttrReader { - bytes - } - ) - ) - ); - self.curr_offset = self.attr_bytes.len(); - return item; - } - - let typ = u16::from_be_bytes(bytes[0..2].try_into().unwrap()); - let transaction_id = self.transaction_id; - - let res = match typ { - 0x0001 => Ok(Attribute::MappedAddress(MappedAddressAttributeReader { bytes })), - 0x0002 => Ok(Attribute::ResponseAddress(ResponseAddressAttributeReader { mapped_address_reader: MappedAddressAttributeReader { bytes } })), - 0x0003 => Ok(Attribute::ChangeAddress(ChangeAddressAttributeReader { mapped_address_reader: MappedAddressAttributeReader { bytes } })), - 0x0004 => Ok(Attribute::SourceAddress(SourceAddressAttributeReader { mapped_address_reader: MappedAddressAttributeReader { bytes } })), - 0x0005 => Ok(Attribute::ChangedAddress(ChangedAddressAttributeReader { mapped_address_reader: MappedAddressAttributeReader { bytes } })), - 0x0006 => Ok(Attribute::Username(UsernameAttributeReader { bytes })), - 0x0007 => Ok(Attribute::Password(PasswordAttributeReader { bytes })), - 0x0008 => Ok(Attribute::MessageIntegrity(MessageIntegrityAttributeReader { bytes })), - 0x000A => Ok(Attribute::UnknownAttributes(UnknownAttributesAttributeReader { bytes })), - 0x000B => Ok(Attribute::ReflectedFrom(ReflectedFromAttributeReader { mapped_address_reader: MappedAddressAttributeReader { bytes } })), - 0x0009 => Ok(Attribute::ErrorCode(ErrorCodeAttributeReader { bytes })), - 0x0014 => Ok(Attribute::Realm(RealmAttributeReader { bytes })), - 0x0015 => Ok(Attribute::Nonce(NonceAttributeReader { bytes })), - 0x0020 => Ok(Attribute::XorMappedAddress(XorMappedAddressAttributeReader { bytes, transaction_id })), - 0x8020 => Ok(Attribute::OptXorMappedAddress(OptXorMappedAddressAttributeReader { xor_mapped_address_reader: XorMappedAddressAttributeReader { bytes, transaction_id } })), - 0x8022 => Ok(Attribute::Software(SoftwareAttributeReader { bytes })), - 0x8023 => Ok(Attribute::AlternateServer(AlternateServerAttributeReader { mapped_address_reader: MappedAddressAttributeReader { bytes } })), - 0x802b => Ok(Attribute::ResponseOrigin(ResponseOriginAttributeReader { mapped_address_reader: MappedAddressAttributeReader { bytes } })), - 0x802c => Ok(Attribute::OtherAddress(OtherAddressAttributeReader { mapped_address_reader: MappedAddressAttributeReader { bytes } })), - 0x8028 => Ok(Attribute::Fingerprint(FingerprintAttributeReader { bytes })), - _ => Err(NonParsableAttribute::Unknown(UnknownAttrReader { bytes })) - }; - - let offset_delta = match &res { - Ok(attr) => attr.get_total_length() as usize, - Err(NonParsableAttribute::Unknown(reader)) => reader.get_total_length() as usize, - Err(NonParsableAttribute::Malformed(_)) => self.attr_bytes.len() - self.curr_offset, - }; - - self.curr_offset += offset_delta; - - Some(res) - } -} - -pub struct StunMessageReader<'a> { - pub(crate) bytes: &'a [u8], -} - -pub enum ComplianceError {} - -impl StunMessageReader<'_> { - pub fn get_message_type(&self) -> u16 { - u16::from_be_bytes(self.bytes[0..2].try_into().unwrap()) - } - - pub fn get_method(&self) -> Result { - let method_code = self.get_method_raw(); - match method_code { - 1 => Ok(Method::Binding), - _ => Err(method_code) - } - } - - pub fn get_method_raw(&self) -> u16 { - let msg_type = self.get_message_type(); - let method_code: u16 = msg_type & 0b11111011101111; - method_code - } - - pub fn get_class(&self) -> MessageClass { - let class = self.get_class_raw(); - match class { - 0b000000000 => MessageClass::Request, - 0b000010000 => MessageClass::Indirection, - 0b100000000 => MessageClass::SuccessResponse, - 0b100010000 => MessageClass::ErrorResponse, - _ => panic!("Impossible message class") - } - } - - pub fn get_class_raw(&self) -> u16 { - let msg_type = self.get_message_type(); - let class = msg_type & !0b11111011101111; - class - } - - pub fn get_length(&self) -> u16 { - u16::from_be_bytes(self.bytes[2..4].try_into().unwrap()) - } - - pub fn get_attrs(&self) -> Iter { - Iter { - attr_bytes: &self.bytes[20..(self.bytes.len())], - curr_offset: 0, - transaction_id: self.bytes[8..20].try_into().unwrap(), - } - } - - pub fn check_header_spec_compliance(&self) -> Vec { todo!() } - - pub fn is_compliant(&self) -> bool { - if !self.check_header_spec_compliance().is_empty() { return false; } - - for attr in self.get_attrs() { - match attr { - Ok(attr) => if !attr.check_compliance().is_empty() { return false; } - Err(_) => return false, - } - } - - true - } -} diff --git a/src/stun_codec/attrs/alternate_server.rs b/src/stun_codec/attrs/alternate_server.rs new file mode 100644 index 000000000..cd8196231 --- /dev/null +++ b/src/stun_codec/attrs/alternate_server.rs @@ -0,0 +1,50 @@ +use std::net::IpAddr; +use super::mapped_address::MappedAddressAttributeReader; +use super::super::enums::{AddressFamily, ComplianceError, RfcSpec}; +use super::base::GenericAttrReader; + +pub struct AlternateServerAttributeReader<'a> { + mapped_address_reader: MappedAddressAttributeReader<'a>, +} + +impl<'a> AlternateServerAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { + mapped_address_reader: MappedAddressAttributeReader::new(bytes) + } + } + + pub fn get_address_family(&self) -> Result { + self.mapped_address_reader.get_address_family() + } + + pub fn get_address_family_raw(&self) -> u8 { + self.mapped_address_reader.get_address_family_raw() + } + + pub fn get_port(&self) -> u16 { + self.mapped_address_reader.get_port() + } + + pub fn get_address(&self) -> Result { + self.mapped_address_reader.get_address() + } +} + +impl GenericAttrReader for AlternateServerAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.mapped_address_reader.get_bytes() + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc5389 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + false + } +} \ No newline at end of file diff --git a/src/stun_codec/attrs/base/malformed.rs b/src/stun_codec/attrs/base/malformed.rs new file mode 100644 index 000000000..736c0d250 --- /dev/null +++ b/src/stun_codec/attrs/base/malformed.rs @@ -0,0 +1,38 @@ +use std::cmp::min; +use std::convert::TryInto; + +pub struct MalformedAttrReader<'a> { + bytes: &'a [u8], +} + +impl<'a> MalformedAttrReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { bytes } + } + + pub fn get_type_raw(&self) -> u16 { + match self.bytes.len() { + 0 => 0, + 1 => u8::from_be(self.bytes[0]) as u16, + _ => u16::from_be_bytes(self.bytes[0..2].try_into().unwrap()), + } + } + + pub fn get_value_length_raw(&self) -> u16 { + match self.bytes.len() { + 0 | 1 | 2 | 3 | 4 => 0, + _ => u16::from_be_bytes(self.bytes[2..4].try_into().unwrap()), + } + } + + pub fn get_value_raw(&self) -> &[u8] { + match self.bytes.len() { + 0 | 1 | 2 | 3 | 4 => &self.bytes[0..0], + _ => { + let length_raw = self.get_value_length_raw() as usize; + let target_value_size = min(length_raw, self.bytes.len() - 4) / 4; + &self.bytes[5..target_value_size] + } + } + } +} diff --git a/src/stun_codec/attrs/base/mod.rs b/src/stun_codec/attrs/base/mod.rs new file mode 100644 index 000000000..24e6c69e7 --- /dev/null +++ b/src/stun_codec/attrs/base/mod.rs @@ -0,0 +1,7 @@ +mod malformed; +mod unknown; +mod shared; + +pub use malformed::*; +pub use unknown::*; +pub use shared::*; diff --git a/src/stun_codec/attrs/base/shared.rs b/src/stun_codec/attrs/base/shared.rs new file mode 100644 index 000000000..100ecf1d7 --- /dev/null +++ b/src/stun_codec/attrs/base/shared.rs @@ -0,0 +1,40 @@ +use std::convert::TryInto; +use super::malformed::MalformedAttrReader; +use super::unknown::UnknownAttrReader; +use super::super::super::enums::{ComplianceError, ComprehensionCategory, RfcSpec}; + +pub enum NonParsableAttribute<'a> { + Unknown(UnknownAttrReader<'a>), + Malformed(MalformedAttrReader<'a>), +} + +pub trait GenericAttrReader { + fn get_bytes(&self) -> &[u8]; + + fn get_value_raw(&self) -> &[u8] { + &self.get_bytes()[4..(self.get_value_length() as usize)] + } + + fn get_type_raw(&self) -> u16 { + u16::from_be_bytes(self.get_bytes()[0..2].try_into().unwrap()) + } + + fn get_value_length(&self) -> u16 { + u16::from_be_bytes(self.get_bytes()[2..4].try_into().unwrap()) + } + + fn get_total_length(&self) -> u16 { + 4 + ((self.get_value_length() + 4 - 1) & (-4i16 as u16)) + } + + fn get_rfc_spec(&self) -> RfcSpec; + + fn get_comprehension_category(&self) -> ComprehensionCategory { + let typ = self.get_type_raw(); + if typ <= 0x7FFF { ComprehensionCategory::Required } else { ComprehensionCategory::Optional } + } + + fn check_compliance(&self) -> Vec; + + fn is_deprecated(&self) -> bool; +} diff --git a/src/stun_codec/attrs/base/unknown.rs b/src/stun_codec/attrs/base/unknown.rs new file mode 100644 index 000000000..b2c35f789 --- /dev/null +++ b/src/stun_codec/attrs/base/unknown.rs @@ -0,0 +1,31 @@ +use std::convert::TryInto; +use super::super::super::enums::ComprehensionCategory; + +pub struct UnknownAttrReader<'a> { + bytes: &'a [u8], +} + +impl<'a> UnknownAttrReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { bytes } + } + + pub fn get_value_raw(&self) -> &[u8] { + &self.bytes[4..(self.get_value_length() as usize)] + } + + pub fn get_type_raw(&self) -> u16 { + u16::from_be_bytes(self.bytes[0..2].try_into().unwrap()) + } + + pub fn get_comprehension_category(&self) -> ComprehensionCategory { + let typ = self.get_type_raw(); + if typ <= 0x7FFF { ComprehensionCategory::Required } else { ComprehensionCategory::Optional } + } + + pub fn get_value_length(&self) -> u16 { + u16::from_be_bytes(self.bytes[2..4].try_into().unwrap()) + } + + pub fn get_total_length(&self) -> u16 { 4 + ((self.get_value_length() + 4 - 1) & (-4i16 as u16)) } +} diff --git a/src/stun_codec/attrs/change_address.rs b/src/stun_codec/attrs/change_address.rs new file mode 100644 index 000000000..92a6b0258 --- /dev/null +++ b/src/stun_codec/attrs/change_address.rs @@ -0,0 +1,51 @@ +use std::net::IpAddr; + +use super::base::GenericAttrReader; +use super::mapped_address::MappedAddressAttributeReader; +use super::super::enums::{AddressFamily, ComplianceError, RfcSpec}; + +pub struct ChangeAddressAttributeReader<'a> { + mapped_address_reader: MappedAddressAttributeReader<'a>, +} + +impl<'a> ChangeAddressAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { + mapped_address_reader: MappedAddressAttributeReader::new(bytes) + } + } + + pub fn get_address_family(&self) -> Result { + self.mapped_address_reader.get_address_family() + } + + pub fn get_address_family_raw(&self) -> u8 { + self.mapped_address_reader.get_address_family_raw() + } + + pub fn get_port(&self) -> u16 { + self.mapped_address_reader.get_port() + } + + pub fn get_address(&self) -> Result { + self.mapped_address_reader.get_address() + } +} + +impl GenericAttrReader for ChangeAddressAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.mapped_address_reader.get_bytes() + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc3489 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + true + } +} diff --git a/src/stun_codec/attrs/changed_address.rs b/src/stun_codec/attrs/changed_address.rs new file mode 100644 index 000000000..c3b23076c --- /dev/null +++ b/src/stun_codec/attrs/changed_address.rs @@ -0,0 +1,50 @@ +use std::net::IpAddr; +use super::mapped_address::MappedAddressAttributeReader; +use super::super::enums::{AddressFamily, ComplianceError, RfcSpec}; +use super::base::GenericAttrReader; + +pub struct ChangedAddressAttributeReader<'a> { + mapped_address_reader: MappedAddressAttributeReader<'a>, +} + +impl<'a> ChangedAddressAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { + mapped_address_reader: MappedAddressAttributeReader::new(bytes) + } + } + + pub fn get_address_family(&self) -> Result { + self.mapped_address_reader.get_address_family() + } + + pub fn get_address_family_raw(&self) -> u8 { + self.mapped_address_reader.get_address_family_raw() + } + + pub fn get_port(&self) -> u16 { + self.mapped_address_reader.get_port() + } + + pub fn get_address(&self) -> Result { + self.mapped_address_reader.get_address() + } +} + +impl GenericAttrReader for ChangedAddressAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.mapped_address_reader.get_bytes() + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc3489 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + true + } +} diff --git a/src/stun_codec/attrs/error_code.rs b/src/stun_codec/attrs/error_code.rs new file mode 100644 index 000000000..2bc3a5bee --- /dev/null +++ b/src/stun_codec/attrs/error_code.rs @@ -0,0 +1,62 @@ +use std::str; +use std::str::Utf8Error; + +use super::super::enums::{ComplianceError, ErrorCode, RfcSpec}; +use super::base::GenericAttrReader; + +pub struct ErrorCodeAttributeReader<'a> { + bytes: &'a [u8], +} + +impl<'a> ErrorCodeAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { bytes } + } + + pub fn get_error(&self) -> Result { + let error_code = self.get_error_code_raw(); + match error_code { + 300 => Ok(ErrorCode::TryAlternate), + 400 => Ok(ErrorCode::BadRequest), + 401 => Ok(ErrorCode::Unauthorized), + 420 => Ok(ErrorCode::UnknownAttribute), + 438 => Ok(ErrorCode::StaleNonce), + 500 => Ok(ErrorCode::InternalServerError), + _ => Err(error_code) + } + } + + pub fn get_reason(&self) -> Result<&str, Utf8Error> { + str::from_utf8(&self.bytes[4..(4 + self.get_value_length() - 2) as usize]) + } + + pub fn get_error_code_raw(&self) -> u16 { + self.get_class() as u16 * 100 + self.get_number() as u16 + } + + pub fn get_class(&self) -> u8 { + self.bytes[5] >> 5 + } + + pub fn get_number(&self) -> u8 { + self.bytes[6] + } +} + +impl GenericAttrReader for ErrorCodeAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.bytes + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc5389 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + true + } +} diff --git a/src/stun_codec/attrs/fingerprint.rs b/src/stun_codec/attrs/fingerprint.rs new file mode 100644 index 000000000..159bb3a9f --- /dev/null +++ b/src/stun_codec/attrs/fingerprint.rs @@ -0,0 +1,35 @@ +use std::convert::TryInto; +use super::super::enums::{ComplianceError, RfcSpec}; +use super::base::GenericAttrReader; + +pub struct FingerprintAttributeReader<'a> { + bytes: &'a [u8], +} + +impl<'a> FingerprintAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { bytes } + } + + pub fn get_checksum(&self) -> u32 { + u32::from_be_bytes(self.bytes[2..2 + self.get_value_length() as usize].try_into().unwrap()) ^ 0x5354554E + } +} + +impl GenericAttrReader for FingerprintAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.bytes + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc5389 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + true + } +} diff --git a/src/stun_codec/attrs/mapped_address.rs b/src/stun_codec/attrs/mapped_address.rs new file mode 100644 index 000000000..09f41b944 --- /dev/null +++ b/src/stun_codec/attrs/mapped_address.rs @@ -0,0 +1,62 @@ +use std::convert::TryInto; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +use super::super::enums::{AddressFamily, ComplianceError, RfcSpec}; +use super::base::GenericAttrReader; + +pub struct MappedAddressAttributeReader<'a> { + bytes: &'a [u8], +} + +impl<'a> MappedAddressAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { bytes } + } + + pub fn get_address_family(&self) -> Result { + let family_code = self.get_address_family_raw(); + match family_code { + 1 => Ok(AddressFamily::V4), + 2 => Ok(AddressFamily::V6), + _ => Err(family_code) + } + } + + pub fn get_address_family_raw(&self) -> u8 { + self.bytes[5] + } + + pub fn get_port(&self) -> u16 { + u16::from_be_bytes(self.bytes[6..8].try_into().unwrap()) + } + + pub fn get_address(&self) -> Result { + match self.get_address_family()? { + AddressFamily::V4 => { + let ip_num = u32::from_be_bytes(self.bytes[8..12].try_into().unwrap()); + Ok(IpAddr::V4(Ipv4Addr::from(ip_num))) + } + AddressFamily::V6 => { + let ip_num = u128::from_be_bytes(self.bytes[8..24].try_into().unwrap()); + Ok(IpAddr::V6(Ipv6Addr::from(ip_num))) + } + } + } +} + +impl GenericAttrReader for MappedAddressAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.bytes + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc3489 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + false + } +} diff --git a/src/stun_codec/attrs/message_integrity.rs b/src/stun_codec/attrs/message_integrity.rs new file mode 100644 index 000000000..3a19671df --- /dev/null +++ b/src/stun_codec/attrs/message_integrity.rs @@ -0,0 +1,35 @@ +use std::convert::TryInto; +use super::super::enums::{ComplianceError, RfcSpec}; +use super::base::GenericAttrReader; + +pub struct MessageIntegrityAttributeReader<'a> { + bytes: &'a [u8], +} + +impl<'a> MessageIntegrityAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { bytes } + } + + pub fn get_digest(&self) -> &[u8; 20] { + self.bytes[2..2 + self.get_value_length() as usize].try_into().unwrap() + } +} + +impl GenericAttrReader for MessageIntegrityAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.bytes + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc5389 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + true + } +} diff --git a/src/stun_codec/attrs/mod.rs b/src/stun_codec/attrs/mod.rs new file mode 100644 index 000000000..ca2424608 --- /dev/null +++ b/src/stun_codec/attrs/mod.rs @@ -0,0 +1,270 @@ +mod base; +mod response_origin; +mod alternate_server; +mod other_address; +mod xor_mapped_address; +mod opt_xor_mapped_address; +mod mapped_address; +mod response_address; +mod change_address; +mod source_address; +mod changed_address; +mod reflected_from; +mod username; +mod password; +mod realm; +mod nonce; +mod unknown_attributes; +mod message_integrity; +mod fingerprint; +mod error_code; +mod software; + +pub use alternate_server::AlternateServerAttributeReader; +pub use change_address::ChangeAddressAttributeReader; +pub use changed_address::ChangedAddressAttributeReader; +pub use error_code::ErrorCodeAttributeReader; +pub use fingerprint::FingerprintAttributeReader; +pub use mapped_address::MappedAddressAttributeReader; +pub use message_integrity::MessageIntegrityAttributeReader; +pub use nonce::NonceAttributeReader; +pub use opt_xor_mapped_address::OptXorMappedAddressAttributeReader; +pub use other_address::OtherAddressAttributeReader; +pub use password::PasswordAttributeReader; +pub use realm::RealmAttributeReader; +pub use reflected_from::ReflectedFromAttributeReader; +pub use response_address::ResponseAddressAttributeReader; +pub use response_origin::ResponseOriginAttributeReader; +pub use software::SoftwareAttributeReader; +pub use source_address::SourceAddressAttributeReader; +pub use unknown_attributes::UnknownAttributesAttributeReader; +pub use username::UsernameAttributeReader; +pub use xor_mapped_address::XorMappedAddressAttributeReader; +pub use base::*; + +use crate::stun_codec::enums::{ComplianceError, RfcSpec}; + +pub enum Attribute<'a> { + MappedAddress(MappedAddressAttributeReader<'a>), + ReflectedFrom(ReflectedFromAttributeReader<'a>), + ResponseAddress(ResponseAddressAttributeReader<'a>), + ChangeAddress(ChangeAddressAttributeReader<'a>), + SourceAddress(SourceAddressAttributeReader<'a>), + ChangedAddress(ChangedAddressAttributeReader<'a>), + XorMappedAddress(XorMappedAddressAttributeReader<'a>), + OptXorMappedAddress(OptXorMappedAddressAttributeReader<'a>), + OtherAddress(OtherAddressAttributeReader<'a>), + ResponseOrigin(ResponseOriginAttributeReader<'a>), + Username(UsernameAttributeReader<'a>), + Password(PasswordAttributeReader<'a>), + MessageIntegrity(MessageIntegrityAttributeReader<'a>), + Fingerprint(FingerprintAttributeReader<'a>), + ErrorCode(ErrorCodeAttributeReader<'a>), + Realm(RealmAttributeReader<'a>), + Nonce(NonceAttributeReader<'a>), + UnknownAttributes(UnknownAttributesAttributeReader<'a>), + Software(SoftwareAttributeReader<'a>), + AlternateServer(AlternateServerAttributeReader<'a>), +} + +impl GenericAttrReader for Attribute<'_> { + fn get_bytes(&self) -> &[u8] { + match self { + Attribute::MappedAddress(r) => r.get_bytes(), + Attribute::ResponseAddress(r) => r.get_bytes(), + Attribute::ChangeAddress(r) => r.get_bytes(), + Attribute::SourceAddress(r) => r.get_bytes(), + Attribute::ChangedAddress(r) => r.get_bytes(), + Attribute::XorMappedAddress(r) => r.get_bytes(), + Attribute::OptXorMappedAddress(r) => r.get_bytes(), + Attribute::OtherAddress(r) => r.get_bytes(), + Attribute::ResponseOrigin(r) => r.get_bytes(), + Attribute::Username(r) => r.get_bytes(), + Attribute::Password(r) => r.get_bytes(), + Attribute::MessageIntegrity(r) => r.get_bytes(), + Attribute::Fingerprint(r) => r.get_bytes(), + Attribute::ErrorCode(r) => r.get_bytes(), + Attribute::Realm(r) => r.get_bytes(), + Attribute::Nonce(r) => r.get_bytes(), + Attribute::UnknownAttributes(r) => r.get_bytes(), + Attribute::ReflectedFrom(r) => r.get_bytes(), + Attribute::Software(r) => r.get_bytes(), + Attribute::AlternateServer(r) => r.get_bytes(), + } + } + + fn get_value_raw(&self) -> &[u8] { + match self { + Attribute::MappedAddress(r) => r.get_value_raw(), + Attribute::ResponseAddress(r) => r.get_value_raw(), + Attribute::ChangeAddress(r) => r.get_value_raw(), + Attribute::SourceAddress(r) => r.get_value_raw(), + Attribute::ChangedAddress(r) => r.get_value_raw(), + Attribute::XorMappedAddress(r) => r.get_value_raw(), + Attribute::OptXorMappedAddress(r) => r.get_value_raw(), + Attribute::OtherAddress(r) => r.get_value_raw(), + Attribute::ResponseOrigin(r) => r.get_value_raw(), + Attribute::Username(r) => r.get_value_raw(), + Attribute::Password(r) => r.get_value_raw(), + Attribute::MessageIntegrity(r) => r.get_value_raw(), + Attribute::Fingerprint(r) => r.get_value_raw(), + Attribute::ErrorCode(r) => r.get_value_raw(), + Attribute::Realm(r) => r.get_value_raw(), + Attribute::Nonce(r) => r.get_value_raw(), + Attribute::UnknownAttributes(r) => r.get_value_raw(), + Attribute::ReflectedFrom(r) => r.get_value_raw(), + Attribute::Software(r) => r.get_value_raw(), + Attribute::AlternateServer(r) => r.get_value_raw(), + } + } + + fn get_type_raw(&self) -> u16 { + match self { + Attribute::MappedAddress(r) => r.get_type_raw(), + Attribute::ResponseAddress(r) => r.get_type_raw(), + Attribute::ChangeAddress(r) => r.get_type_raw(), + Attribute::SourceAddress(r) => r.get_type_raw(), + Attribute::ChangedAddress(r) => r.get_type_raw(), + Attribute::XorMappedAddress(r) => r.get_type_raw(), + Attribute::OptXorMappedAddress(r) => r.get_type_raw(), + Attribute::OtherAddress(r) => r.get_type_raw(), + Attribute::ResponseOrigin(r) => r.get_type_raw(), + Attribute::Username(r) => r.get_type_raw(), + Attribute::Password(r) => r.get_type_raw(), + Attribute::MessageIntegrity(r) => r.get_type_raw(), + Attribute::Fingerprint(r) => r.get_type_raw(), + Attribute::ErrorCode(r) => r.get_type_raw(), + Attribute::Realm(r) => r.get_type_raw(), + Attribute::Nonce(r) => r.get_type_raw(), + Attribute::UnknownAttributes(r) => r.get_type_raw(), + Attribute::ReflectedFrom(r) => r.get_type_raw(), + Attribute::Software(r) => r.get_type_raw(), + Attribute::AlternateServer(r) => r.get_type_raw(), + } + } + + fn get_value_length(&self) -> u16 { + match self { + Attribute::MappedAddress(r) => r.get_value_length(), + Attribute::ResponseAddress(r) => r.get_value_length(), + Attribute::ChangeAddress(r) => r.get_value_length(), + Attribute::SourceAddress(r) => r.get_value_length(), + Attribute::ChangedAddress(r) => r.get_value_length(), + Attribute::XorMappedAddress(r) => r.get_value_length(), + Attribute::OptXorMappedAddress(r) => r.get_value_length(), + Attribute::OtherAddress(r) => r.get_value_length(), + Attribute::ResponseOrigin(r) => r.get_value_length(), + Attribute::Username(r) => r.get_value_length(), + Attribute::Password(r) => r.get_value_length(), + Attribute::MessageIntegrity(r) => r.get_value_length(), + Attribute::Fingerprint(r) => r.get_value_length(), + Attribute::ErrorCode(r) => r.get_value_length(), + Attribute::Realm(r) => r.get_value_length(), + Attribute::Nonce(r) => r.get_value_length(), + Attribute::UnknownAttributes(r) => r.get_value_length(), + Attribute::ReflectedFrom(r) => r.get_value_length(), + Attribute::Software(r) => r.get_value_length(), + Attribute::AlternateServer(r) => r.get_value_length(), + } + } + + fn get_total_length(&self) -> u16 { + match self { + Attribute::MappedAddress(r) => r.get_total_length(), + Attribute::ResponseAddress(r) => r.get_total_length(), + Attribute::ChangeAddress(r) => r.get_total_length(), + Attribute::SourceAddress(r) => r.get_total_length(), + Attribute::ChangedAddress(r) => r.get_total_length(), + Attribute::XorMappedAddress(r) => r.get_total_length(), + Attribute::OptXorMappedAddress(r) => r.get_total_length(), + Attribute::OtherAddress(r) => r.get_total_length(), + Attribute::ResponseOrigin(r) => r.get_total_length(), + Attribute::Username(r) => r.get_total_length(), + Attribute::Password(r) => r.get_total_length(), + Attribute::MessageIntegrity(r) => r.get_total_length(), + Attribute::Fingerprint(r) => r.get_total_length(), + Attribute::ErrorCode(r) => r.get_total_length(), + Attribute::Realm(r) => r.get_total_length(), + Attribute::Nonce(r) => r.get_total_length(), + Attribute::UnknownAttributes(r) => r.get_total_length(), + Attribute::ReflectedFrom(r) => r.get_total_length(), + Attribute::Software(r) => r.get_total_length(), + Attribute::AlternateServer(r) => r.get_total_length(), + } + } + + fn get_rfc_spec(&self) -> RfcSpec { + match self { + Attribute::MappedAddress(r) => r.get_rfc_spec(), + Attribute::ResponseAddress(r) => r.get_rfc_spec(), + Attribute::ChangeAddress(r) => r.get_rfc_spec(), + Attribute::SourceAddress(r) => r.get_rfc_spec(), + Attribute::ChangedAddress(r) => r.get_rfc_spec(), + Attribute::XorMappedAddress(r) => r.get_rfc_spec(), + Attribute::OptXorMappedAddress(r) => r.get_rfc_spec(), + Attribute::OtherAddress(r) => r.get_rfc_spec(), + Attribute::ResponseOrigin(r) => r.get_rfc_spec(), + Attribute::Username(r) => r.get_rfc_spec(), + Attribute::Password(r) => r.get_rfc_spec(), + Attribute::MessageIntegrity(r) => r.get_rfc_spec(), + Attribute::Fingerprint(r) => r.get_rfc_spec(), + Attribute::ErrorCode(r) => r.get_rfc_spec(), + Attribute::Realm(r) => r.get_rfc_spec(), + Attribute::Nonce(r) => r.get_rfc_spec(), + Attribute::UnknownAttributes(r) => r.get_rfc_spec(), + Attribute::ReflectedFrom(r) => r.get_rfc_spec(), + Attribute::Software(r) => r.get_rfc_spec(), + Attribute::AlternateServer(r) => r.get_rfc_spec(), + } + } + + fn check_compliance(&self) -> Vec { + match self { + Attribute::MappedAddress(r) => r.check_compliance(), + Attribute::ResponseAddress(r) => r.check_compliance(), + Attribute::ChangeAddress(r) => r.check_compliance(), + Attribute::SourceAddress(r) => r.check_compliance(), + Attribute::ChangedAddress(r) => r.check_compliance(), + Attribute::XorMappedAddress(r) => r.check_compliance(), + Attribute::OptXorMappedAddress(r) => r.check_compliance(), + Attribute::OtherAddress(r) => r.check_compliance(), + Attribute::ResponseOrigin(r) => r.check_compliance(), + Attribute::Username(r) => r.check_compliance(), + Attribute::Password(r) => r.check_compliance(), + Attribute::MessageIntegrity(r) => r.check_compliance(), + Attribute::Fingerprint(r) => r.check_compliance(), + Attribute::ErrorCode(r) => r.check_compliance(), + Attribute::Realm(r) => r.check_compliance(), + Attribute::Nonce(r) => r.check_compliance(), + Attribute::UnknownAttributes(r) => r.check_compliance(), + Attribute::ReflectedFrom(r) => r.check_compliance(), + Attribute::Software(r) => r.check_compliance(), + Attribute::AlternateServer(r) => r.check_compliance(), + } + } + + fn is_deprecated(&self) -> bool { + match self { + Attribute::MappedAddress(r) => r.is_deprecated(), + Attribute::ResponseAddress(r) => r.is_deprecated(), + Attribute::ChangeAddress(r) => r.is_deprecated(), + Attribute::SourceAddress(r) => r.is_deprecated(), + Attribute::ChangedAddress(r) => r.is_deprecated(), + Attribute::XorMappedAddress(r) => r.is_deprecated(), + Attribute::OptXorMappedAddress(r) => r.is_deprecated(), + Attribute::OtherAddress(r) => r.is_deprecated(), + Attribute::ResponseOrigin(r) => r.is_deprecated(), + Attribute::Username(r) => r.is_deprecated(), + Attribute::Password(r) => r.is_deprecated(), + Attribute::MessageIntegrity(r) => r.is_deprecated(), + Attribute::Fingerprint(r) => r.is_deprecated(), + Attribute::ErrorCode(r) => r.is_deprecated(), + Attribute::Realm(r) => r.is_deprecated(), + Attribute::Nonce(r) => r.is_deprecated(), + Attribute::UnknownAttributes(r) => r.is_deprecated(), + Attribute::ReflectedFrom(r) => r.is_deprecated(), + Attribute::Software(r) => r.is_deprecated(), + Attribute::AlternateServer(r) => r.is_deprecated(), + } + } +} diff --git a/src/stun_codec/attrs/nonce.rs b/src/stun_codec/attrs/nonce.rs new file mode 100644 index 000000000..6b8522629 --- /dev/null +++ b/src/stun_codec/attrs/nonce.rs @@ -0,0 +1,37 @@ +use std::str; +use std::str::Utf8Error; + +use super::super::enums::{ComplianceError, RfcSpec}; +use super::base::GenericAttrReader; + +pub struct NonceAttributeReader<'a> { + bytes: &'a [u8], +} + +impl<'a> NonceAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { bytes } + } + + pub fn get_nonce(&self) -> Result<&str, Utf8Error> { + str::from_utf8(&self.bytes[2..2 + self.get_value_length() as usize]) + } +} + +impl GenericAttrReader for NonceAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.bytes + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc3489 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + false + } +} diff --git a/src/stun_codec/attrs/opt_xor_mapped_address.rs b/src/stun_codec/attrs/opt_xor_mapped_address.rs new file mode 100644 index 000000000..5ee868e02 --- /dev/null +++ b/src/stun_codec/attrs/opt_xor_mapped_address.rs @@ -0,0 +1,50 @@ +use std::net::IpAddr; +use super::xor_mapped_address::XorMappedAddressAttributeReader; +use super::super::enums::{AddressFamily, ComplianceError, RfcSpec}; +use super::base::GenericAttrReader; + +pub struct OptXorMappedAddressAttributeReader<'a> { + xor_mapped_address_reader: XorMappedAddressAttributeReader<'a>, +} + +impl<'a> OptXorMappedAddressAttributeReader<'a> { + pub fn new(bytes: &'a [u8], transaction_id: &'a [u8; 12]) -> Self { + Self { + xor_mapped_address_reader: XorMappedAddressAttributeReader::new(bytes, transaction_id) + } + } + + pub fn get_address_family(&self) -> Result { + self.xor_mapped_address_reader.get_address_family() + } + + pub fn get_address_family_raw(&self) -> u8 { + self.xor_mapped_address_reader.get_address_family_raw() + } + + pub fn get_port(&self) -> u16 { + self.xor_mapped_address_reader.get_port() + } + + pub fn get_address(&self) -> Result { + self.xor_mapped_address_reader.get_address() + } +} + +impl GenericAttrReader for OptXorMappedAddressAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.xor_mapped_address_reader.get_bytes() + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc3489 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + true + } +} diff --git a/src/stun_codec/attrs/other_address.rs b/src/stun_codec/attrs/other_address.rs new file mode 100644 index 000000000..3707c4357 --- /dev/null +++ b/src/stun_codec/attrs/other_address.rs @@ -0,0 +1,50 @@ +use std::net::IpAddr; +use super::mapped_address::MappedAddressAttributeReader; +use super::super::enums::{AddressFamily, ComplianceError, RfcSpec}; +use super::base::GenericAttrReader; + +pub struct OtherAddressAttributeReader<'a> { + mapped_address_reader: MappedAddressAttributeReader<'a>, +} + +impl<'a> OtherAddressAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { + mapped_address_reader: MappedAddressAttributeReader::new(bytes) + } + } + + pub fn get_address_family(&self) -> Result { + self.mapped_address_reader.get_address_family() + } + + pub fn get_address_family_raw(&self) -> u8 { + self.mapped_address_reader.get_address_family_raw() + } + + pub fn get_port(&self) -> u16 { + self.mapped_address_reader.get_port() + } + + pub fn get_address(&self) -> Result { + self.mapped_address_reader.get_address() + } +} + +impl GenericAttrReader for OtherAddressAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.mapped_address_reader.get_bytes() + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc5389 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + false + } +} diff --git a/src/stun_codec/attrs/password.rs b/src/stun_codec/attrs/password.rs new file mode 100644 index 000000000..72372a051 --- /dev/null +++ b/src/stun_codec/attrs/password.rs @@ -0,0 +1,37 @@ +use std::str; +use std::str::Utf8Error; + +use super::super::enums::{ComplianceError, RfcSpec}; +use super::base::GenericAttrReader; + +pub struct PasswordAttributeReader<'a> { + bytes: &'a [u8], +} + +impl<'a> PasswordAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { bytes } + } + + pub fn get_password(&self) -> Result<&str, Utf8Error> { + str::from_utf8(&self.bytes[2..2 + self.get_value_length() as usize]) + } +} + +impl GenericAttrReader for PasswordAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.bytes + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc3489 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + true + } +} diff --git a/src/stun_codec/attrs/realm.rs b/src/stun_codec/attrs/realm.rs new file mode 100644 index 000000000..4be12fc94 --- /dev/null +++ b/src/stun_codec/attrs/realm.rs @@ -0,0 +1,37 @@ +use std::str; +use std::str::Utf8Error; + +use super::base::GenericAttrReader; +use super::super::enums::{ComplianceError, RfcSpec}; + +pub struct RealmAttributeReader<'a> { + bytes: &'a [u8], +} + +impl<'a> RealmAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { bytes } + } + + pub fn get_realm(&self) -> Result<&str, Utf8Error> { + str::from_utf8(&self.bytes[2..2 + self.get_value_length() as usize]) + } +} + +impl GenericAttrReader for RealmAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.bytes + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc3489 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + false + } +} diff --git a/src/stun_codec/attrs/reflected_from.rs b/src/stun_codec/attrs/reflected_from.rs new file mode 100644 index 000000000..9e58fa2f7 --- /dev/null +++ b/src/stun_codec/attrs/reflected_from.rs @@ -0,0 +1,50 @@ +use std::net::IpAddr; +use super::mapped_address::MappedAddressAttributeReader; +use super::super::enums::{AddressFamily, ComplianceError, RfcSpec}; +use super::base::GenericAttrReader; + +pub struct ReflectedFromAttributeReader<'a> { + mapped_address_reader: MappedAddressAttributeReader<'a>, +} + +impl<'a> ReflectedFromAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { + mapped_address_reader: MappedAddressAttributeReader::new(bytes) + } + } + + pub fn get_address_family(&self) -> Result { + self.mapped_address_reader.get_address_family() + } + + pub fn get_address_family_raw(&self) -> u8 { + self.mapped_address_reader.get_address_family_raw() + } + + pub fn get_port(&self) -> u16 { + self.mapped_address_reader.get_port() + } + + pub fn get_address(&self) -> Result { + self.mapped_address_reader.get_address() + } +} + +impl GenericAttrReader for ReflectedFromAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.mapped_address_reader.get_bytes() + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc3489 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + true + } +} diff --git a/src/stun_codec/attrs/response_address.rs b/src/stun_codec/attrs/response_address.rs new file mode 100644 index 000000000..6a2b3c4d9 --- /dev/null +++ b/src/stun_codec/attrs/response_address.rs @@ -0,0 +1,50 @@ +use std::net::IpAddr; +use super::mapped_address::MappedAddressAttributeReader; +use super::super::enums::{AddressFamily, ComplianceError, RfcSpec}; +use super::base::GenericAttrReader; + +pub struct ResponseAddressAttributeReader<'a> { + mapped_address_reader: MappedAddressAttributeReader<'a>, +} + +impl<'a> ResponseAddressAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { + mapped_address_reader: MappedAddressAttributeReader::new(bytes) + } + } + + pub fn get_address_family(&self) -> Result { + self.mapped_address_reader.get_address_family() + } + + pub fn get_address_family_raw(&self) -> u8 { + self.mapped_address_reader.get_address_family_raw() + } + + pub fn get_port(&self) -> u16 { + self.mapped_address_reader.get_port() + } + + pub fn get_address(&self) -> Result { + self.mapped_address_reader.get_address() + } +} + +impl GenericAttrReader for ResponseAddressAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.mapped_address_reader.get_bytes() + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc3489 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + true + } +} diff --git a/src/stun_codec/attrs/response_origin.rs b/src/stun_codec/attrs/response_origin.rs new file mode 100644 index 000000000..1481ff9ae --- /dev/null +++ b/src/stun_codec/attrs/response_origin.rs @@ -0,0 +1,50 @@ +use std::net::IpAddr; +use super::mapped_address::MappedAddressAttributeReader; +use super::super::enums::{AddressFamily, ComplianceError, RfcSpec}; +use super::base::GenericAttrReader; + +pub struct ResponseOriginAttributeReader<'a> { + mapped_address_reader: MappedAddressAttributeReader<'a>, +} + +impl<'a> ResponseOriginAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { + mapped_address_reader: MappedAddressAttributeReader::new(bytes) + } + } + + pub fn get_address_family(&self) -> Result { + self.mapped_address_reader.get_address_family() + } + + pub fn get_address_family_raw(&self) -> u8 { + self.mapped_address_reader.get_address_family_raw() + } + + pub fn get_port(&self) -> u16 { + self.mapped_address_reader.get_port() + } + + pub fn get_address(&self) -> Result { + self.mapped_address_reader.get_address() + } +} + +impl GenericAttrReader for ResponseOriginAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.mapped_address_reader.get_bytes() + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc5389 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + false + } +} diff --git a/src/stun_codec/attrs/software.rs b/src/stun_codec/attrs/software.rs new file mode 100644 index 000000000..e4029fa0e --- /dev/null +++ b/src/stun_codec/attrs/software.rs @@ -0,0 +1,37 @@ +use std::str; +use std::str::Utf8Error; + +use super::super::enums::{ComplianceError, RfcSpec}; +use super::base::GenericAttrReader; + +pub struct SoftwareAttributeReader<'a> { + bytes: &'a [u8], +} + +impl<'a> SoftwareAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { bytes } + } + + pub fn get_software(&self) -> Result<&str, Utf8Error> { + str::from_utf8(&self.bytes[2..2 + self.get_value_length() as usize]) + } +} + +impl GenericAttrReader for SoftwareAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.bytes + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc5389 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + false + } +} diff --git a/src/stun_codec/attrs/source_address.rs b/src/stun_codec/attrs/source_address.rs new file mode 100644 index 000000000..819774c42 --- /dev/null +++ b/src/stun_codec/attrs/source_address.rs @@ -0,0 +1,50 @@ +use std::net::IpAddr; +use super::mapped_address::MappedAddressAttributeReader; +use super::super::enums::{AddressFamily, ComplianceError, RfcSpec}; +use super::base::GenericAttrReader; + +pub struct SourceAddressAttributeReader<'a> { + mapped_address_reader: MappedAddressAttributeReader<'a>, +} + +impl<'a> SourceAddressAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { + mapped_address_reader: MappedAddressAttributeReader::new(bytes) + } + } + + pub fn get_address_family(&self) -> Result { + self.mapped_address_reader.get_address_family() + } + + pub fn get_address_family_raw(&self) -> u8 { + self.mapped_address_reader.get_address_family_raw() + } + + pub fn get_port(&self) -> u16 { + self.mapped_address_reader.get_port() + } + + pub fn get_address(&self) -> Result { + self.mapped_address_reader.get_address() + } +} + +impl GenericAttrReader for SourceAddressAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.mapped_address_reader.get_bytes() + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc3489 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + true + } +} diff --git a/src/stun_codec/attrs/unknown_attributes.rs b/src/stun_codec/attrs/unknown_attributes.rs new file mode 100644 index 000000000..f50a9a858 --- /dev/null +++ b/src/stun_codec/attrs/unknown_attributes.rs @@ -0,0 +1,58 @@ +use std::convert::TryInto; + +use super::base::GenericAttrReader; +use super::super::enums::{ComplianceError, RfcSpec}; + +pub struct UnknownAttributesAttributeReader<'a> { + bytes: &'a [u8], +} + +pub struct UnknownAttrIter<'a> { + bytes: &'a [u8], + offset: usize, +} + +impl Iterator for UnknownAttrIter<'_> { + type Item = u16; + + fn next(&mut self) -> Option { + if self.offset == self.bytes.len() { + None + } else { + let attr = u16::from_be_bytes(self.bytes[self.offset..self.offset + 2].try_into().unwrap()); + self.offset += 2; + Some(attr) + } + } +} + +impl<'a> UnknownAttributesAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { bytes } + } + + pub fn get_attr_codes(&self) -> UnknownAttrIter { + UnknownAttrIter { + bytes: &self.bytes[2..2+self.get_value_length() as usize], + offset: 0 + } + } +} + +impl GenericAttrReader for UnknownAttributesAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.bytes + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc3489 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + false + } +} diff --git a/src/stun_codec/attrs/username.rs b/src/stun_codec/attrs/username.rs new file mode 100644 index 000000000..7c60b809a --- /dev/null +++ b/src/stun_codec/attrs/username.rs @@ -0,0 +1,37 @@ +use std::str; +use std::str::Utf8Error; + +use super::base::GenericAttrReader; +use super::super::enums::{ComplianceError, RfcSpec}; + +pub struct UsernameAttributeReader<'a> { + bytes: &'a [u8], +} + +impl<'a> UsernameAttributeReader<'a> { + pub fn new(bytes: &'a [u8]) -> Self { + Self { bytes } + } + + pub fn get_username(&self) -> Result<&str, Utf8Error> { + str::from_utf8(&self.bytes[2..2 + self.get_value_length() as usize]) + } +} + +impl GenericAttrReader for UsernameAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.bytes + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc3489 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + false + } +} diff --git a/src/stun_codec/attrs/xor_mapped_address.rs b/src/stun_codec/attrs/xor_mapped_address.rs new file mode 100644 index 000000000..397e11bd9 --- /dev/null +++ b/src/stun_codec/attrs/xor_mapped_address.rs @@ -0,0 +1,65 @@ +use std::convert::TryInto; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +use super::super::enums::{AddressFamily, ComplianceError, RfcSpec}; +use super::base::GenericAttrReader; + +pub struct XorMappedAddressAttributeReader<'a> { + bytes: &'a [u8], + transaction_id: &'a [u8; 12], +} + +impl<'a> XorMappedAddressAttributeReader<'a> { + pub fn new(bytes: &'a [u8], transaction_id: &'a [u8; 12]) -> Self { + Self { bytes, transaction_id } + } + + pub fn get_address_family(&self) -> Result { + let family_code = self.get_address_family_raw(); + match family_code { + 1 => Ok(AddressFamily::V4), + 2 => Ok(AddressFamily::V6), + _ => Err(family_code) + } + } + + pub fn get_address_family_raw(&self) -> u8 { + self.bytes[5] + } + + pub fn get_port(&self) -> u16 { + u16::from_be_bytes(self.bytes[6..8].try_into().unwrap()) ^ 0x2112 // xor with top half of magic cookie + } + + pub fn get_address(&self) -> Result { + match self.get_address_family()? { + AddressFamily::V4 => { + let ip_num = u32::from_be_bytes(self.bytes[8..12].try_into().unwrap()) ^ 0x2112A442; // xor with magic cookie + Ok(IpAddr::V4(Ipv4Addr::from(ip_num))) + } + AddressFamily::V6 => { + let t_id = self.transaction_id; + let xor_mask = 0x2112A442_u128 << 92 | u128::from(u64::from_ne_bytes(t_id[4..12].try_into().unwrap())) << 64 | u32::from_ne_bytes(t_id[0..4].try_into().unwrap()) as u128; + let ip_num = u128::from_be_bytes(self.bytes[8..24].try_into().unwrap()) ^ xor_mask; + Ok(IpAddr::V6(Ipv6Addr::from(ip_num))) + } + } + } +} + +impl GenericAttrReader for XorMappedAddressAttributeReader<'_> { + fn get_bytes(&self) -> &[u8] { + self.bytes + } + + fn get_rfc_spec(&self) -> RfcSpec { + RfcSpec::Rfc5389 + } + + fn check_compliance(&self) -> Vec { + todo!() + } + + fn is_deprecated(&self) -> bool { + false + } +} diff --git a/src/stun_codec/enums.rs b/src/stun_codec/enums.rs new file mode 100644 index 000000000..abf301d77 --- /dev/null +++ b/src/stun_codec/enums.rs @@ -0,0 +1,46 @@ +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum MessageClass { + Request, + Indirection, + SuccessResponse, + ErrorResponse, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum Method { + Binding +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum ComprehensionCategory { + Required, + Optional, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum RfcSpec { + Rfc3489, + Rfc5245, + Rfc5389, + Rfc5766, + Rfc5780, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum AddressFamily { + V4, + V6, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum ComplianceError {} + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum ErrorCode { + TryAlternate, + BadRequest, + Unauthorized, + UnknownAttribute, + StaleNonce, + InternalServerError, +} \ No newline at end of file diff --git a/src/stun_codec/message.rs b/src/stun_codec/message.rs new file mode 100644 index 000000000..c61209504 --- /dev/null +++ b/src/stun_codec/message.rs @@ -0,0 +1,136 @@ +use std::convert::TryInto; +use super::enums::{ComplianceError, MessageClass, Method}; +use super::attrs::*; + +pub struct StunMessageReader<'a> { + pub(crate) bytes: &'a [u8], +} + +impl StunMessageReader<'_> { + pub fn get_message_type(&self) -> u16 { + u16::from_be_bytes(self.bytes[0..2].try_into().unwrap()) + } + + pub fn get_method(&self) -> Result { + let method_code = self.get_method_raw(); + match method_code { + 1 => Ok(Method::Binding), + _ => Err(method_code) + } + } + + pub fn get_method_raw(&self) -> u16 { + let msg_type = self.get_message_type(); + let method_code: u16 = msg_type & 0b11111011101111; + method_code + } + + pub fn get_class(&self) -> MessageClass { + let class = self.get_class_raw(); + match class { + 0b000000000 => MessageClass::Request, + 0b000010000 => MessageClass::Indirection, + 0b100000000 => MessageClass::SuccessResponse, + 0b100010000 => MessageClass::ErrorResponse, + _ => panic!("Impossible message class") + } + } + + pub fn get_class_raw(&self) -> u16 { + let msg_type = self.get_message_type(); + let class = msg_type & !0b11111011101111; + class + } + + pub fn get_length(&self) -> u16 { + u16::from_be_bytes(self.bytes[2..4].try_into().unwrap()) + } + + pub fn get_attrs(&self) -> Iter { + Iter { + attr_bytes: &self.bytes[20..(self.bytes.len())], + curr_offset: 0, + transaction_id: self.bytes[8..20].try_into().unwrap(), + } + } + + pub fn check_header_spec_compliance(&self) -> Vec { todo!() } + + pub fn is_compliant(&self) -> bool { + if !self.check_header_spec_compliance().is_empty() { return false; } + + for attr in self.get_attrs() { + match attr { + Ok(attr) => if !attr.check_compliance().is_empty() { return false; } + Err(_) => return false, + } + } + + true + } +} + +pub struct Iter<'a> { + attr_bytes: &'a [u8], + curr_offset: usize, + transaction_id: &'a [u8; 12], +} + +impl<'a> Iterator for Iter<'a> { + type Item = Result, NonParsableAttribute<'a>>; + + fn next(&mut self) -> Option { + if self.attr_bytes.len() - self.curr_offset == 0 { return None; } + + let bytes = &self.attr_bytes[self.curr_offset..self.attr_bytes.len()]; + + if self.attr_bytes.len() - self.curr_offset <= 4 { + let item = Some( + Err( + NonParsableAttribute::Malformed( + MalformedAttrReader::new(bytes) + ) + ) + ); + self.curr_offset = self.attr_bytes.len(); + return item; + } + + let typ = u16::from_be_bytes(bytes[0..2].try_into().unwrap()); + let transaction_id = self.transaction_id; + + let res = match typ { + 0x0001 => Ok(Attribute::MappedAddress(MappedAddressAttributeReader::new(bytes))), + 0x0002 => Ok(Attribute::ResponseAddress(ResponseAddressAttributeReader::new(bytes))), + 0x0003 => Ok(Attribute::ChangeAddress(ChangeAddressAttributeReader::new(bytes))), + 0x0004 => Ok(Attribute::SourceAddress(SourceAddressAttributeReader::new(bytes))), + 0x0005 => Ok(Attribute::ChangedAddress(ChangedAddressAttributeReader::new(bytes))), + 0x0006 => Ok(Attribute::Username(UsernameAttributeReader::new(bytes))), + 0x0007 => Ok(Attribute::Password(PasswordAttributeReader::new(bytes))), + 0x0008 => Ok(Attribute::MessageIntegrity(MessageIntegrityAttributeReader::new(bytes))), + 0x000A => Ok(Attribute::UnknownAttributes(UnknownAttributesAttributeReader::new(bytes))), + 0x000B => Ok(Attribute::ReflectedFrom(ReflectedFromAttributeReader::new(bytes))), + 0x0009 => Ok(Attribute::ErrorCode(ErrorCodeAttributeReader::new(bytes))), + 0x0014 => Ok(Attribute::Realm(RealmAttributeReader::new(bytes))), + 0x0015 => Ok(Attribute::Nonce(NonceAttributeReader::new(bytes))), + 0x0020 => Ok(Attribute::XorMappedAddress(XorMappedAddressAttributeReader::new(bytes, transaction_id))), + 0x8020 => Ok(Attribute::OptXorMappedAddress(OptXorMappedAddressAttributeReader::new(bytes, transaction_id))), + 0x8022 => Ok(Attribute::Software(SoftwareAttributeReader::new(bytes))), + 0x8023 => Ok(Attribute::AlternateServer(AlternateServerAttributeReader::new(bytes))), + 0x802b => Ok(Attribute::ResponseOrigin(ResponseOriginAttributeReader::new(bytes))), + 0x802c => Ok(Attribute::OtherAddress(OtherAddressAttributeReader::new(bytes))), + 0x8028 => Ok(Attribute::Fingerprint(FingerprintAttributeReader::new(bytes))), + _ => Err(NonParsableAttribute::Unknown(UnknownAttrReader::new(bytes))) + }; + + let offset_delta = match &res { + Ok(attr) => attr.get_total_length() as usize, + Err(NonParsableAttribute::Unknown(reader)) => reader.get_total_length() as usize, + Err(NonParsableAttribute::Malformed(_)) => self.attr_bytes.len() - self.curr_offset, + }; + + self.curr_offset += offset_delta; + + Some(res) + } +} \ No newline at end of file diff --git a/src/stun_codec/mod.rs b/src/stun_codec/mod.rs new file mode 100644 index 000000000..0683ceaf1 --- /dev/null +++ b/src/stun_codec/mod.rs @@ -0,0 +1,7 @@ +mod enums; +mod attrs; +mod message; + +pub use attrs::*; +pub use enums::*; +pub use message::*;