From: Jason Ish Date: Thu, 8 Sep 2022 16:42:15 +0000 (-0600) Subject: bittorrent-dht: fix values decoding, as a list of peers X-Git-Tag: suricata-7.0.0-rc1~430 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2f9eb5d1dd5fb6319eb184703890cbb013b72a65;p=thirdparty%2Fsuricata.git bittorrent-dht: fix values decoding, as a list of peers The "values" field is not a string, but instead peer information in compact format. Decode this properly and then properly format in the log. --- diff --git a/rust/src/bittorrent_dht/logger.rs b/rust/src/bittorrent_dht/logger.rs index 283f103323..3145a956a3 100644 --- a/rust/src/bittorrent_dht/logger.rs +++ b/rust/src/bittorrent_dht/logger.rs @@ -100,7 +100,10 @@ fn log_bittorrent_dht( if let Some(values) = &response.values { js.open_array("values")?; for value in values { - js.append_string(value)?; + js.start_object()?; + js.set_string("ip", &print_ip_addr(&value.ip))?; + js.set_uint("port", value.port.into())?; + js.close()?; } js.close()?; } diff --git a/rust/src/bittorrent_dht/parser.rs b/rust/src/bittorrent_dht/parser.rs index cdb0db45dc..cc7c44a636 100644 --- a/rust/src/bittorrent_dht/parser.rs +++ b/rust/src/bittorrent_dht/parser.rs @@ -52,7 +52,7 @@ pub struct BitTorrentDHTResponse { /// K(8) closest good nodes in routing table pub nodes: Option>, /// q = get_peers - list of compact peer infos - pub values: Option>, + pub values: Option>, /// q = get_peers - token key required for sender's future /// announce_peer query pub token: Option>, @@ -73,6 +73,12 @@ pub struct Node { pub port: u16, } +#[derive(Debug, Eq, PartialEq)] +pub struct Peer { + pub ip: Vec, + pub port: u16, +} + /// Parse IPv4 node structures. pub fn parse_node(i: &[u8]) -> IResult<&[u8], Node> { let (i, id) = take(20usize)(i)?; @@ -88,6 +94,22 @@ pub fn parse_node(i: &[u8]) -> IResult<&[u8], Node> { )) } +fn parse_peer(i: &[u8]) -> IResult<&[u8], Peer> { + let (i, ip) = if i.len() < 18 { + take(4usize)(i) + } else { + take(16usize)(i) + }?; + let (i, port) = be_u16(i)?; + Ok(( + i, + Peer { + ip: ip.to_vec(), + port, + }, + )) +} + impl FromBencode for BitTorrentDHTRequest { // Try to parse with a `max_depth` of one. // @@ -191,7 +213,7 @@ impl FromBencode for BitTorrentDHTResponse { { let mut id = None; let mut nodes = None; - let mut values = None; + let mut values = vec![]; let mut token = None; let mut dict_dec = object.try_into_dictionary()?; @@ -210,9 +232,14 @@ impl FromBencode for BitTorrentDHTResponse { } } (b"values", value) => { - values = Vec::decode_bencode_object(value) - .context("values") - .map(Some)?; + if let Object::List(mut list) = value { + while let Some(entry) = list.next_object()? { + let (_, peer) = + parse_peer(entry.try_into_bytes().context("values.entry")?) + .map_err(|_| Error::malformed_content("values.entry.peer"))?; + values.push(peer); + } + } } (b"token", value) => { token = value @@ -229,7 +256,11 @@ impl FromBencode for BitTorrentDHTResponse { Ok(BitTorrentDHTResponse { id: id.to_vec(), nodes, - values, + values: if values.is_empty() { + None + } else { + Some(values) + }, token, }) }