From 2d05beac06462ab21b1b993763104594965b49b6 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Fri, 14 Apr 2023 15:01:14 -0700 Subject: [PATCH] Add support for 802.11 A-MSDU aggregates --- src/TunnelEncapsulation.cc | 12 +++ src/TunnelEncapsulation.h | 5 + .../protocol/ieee802_11/IEEE802_11.cc | 87 ++++++++++++++++-- .../protocol/ieee802_11/IEEE802_11.h | 3 + .../core.tunnels.gre-aruba-amsdu/conn.log | 11 +++ .../core.tunnels.gre-aruba-amsdu/tunnel.log | 11 +++ .../btest/Traces/tunnels/gre-aruba-amsdu.pcap | Bin 0 -> 509 bytes .../btest/core/tunnels/gre-aruba-amsdu.zeek | 7 ++ 8 files changed, 127 insertions(+), 9 deletions(-) create mode 100644 testing/btest/Baseline/core.tunnels.gre-aruba-amsdu/conn.log create mode 100644 testing/btest/Baseline/core.tunnels.gre-aruba-amsdu/tunnel.log create mode 100644 testing/btest/Traces/tunnels/gre-aruba-amsdu.pcap create mode 100644 testing/btest/core/tunnels/gre-aruba-amsdu.zeek diff --git a/src/TunnelEncapsulation.cc b/src/TunnelEncapsulation.cc index 3bd503a85a..8fd1041ff6 100644 --- a/src/TunnelEncapsulation.cc +++ b/src/TunnelEncapsulation.cc @@ -3,6 +3,7 @@ #include "zeek/TunnelEncapsulation.h" #include "zeek/Conn.h" +#include "zeek/Reporter.h" #include "zeek/util.h" namespace zeek @@ -56,4 +57,15 @@ bool operator==(const EncapsulationStack& e1, const EncapsulationStack& e2) return true; } +void EncapsulationStack::Pop() + { + if ( Depth() == 0 ) + { + reporter->InternalWarning("Attempted to pop from empty EncapsulationStack\n"); + return; + } + + conns->pop_back(); + } + } // namespace zeek diff --git a/src/TunnelEncapsulation.h b/src/TunnelEncapsulation.h index 88258e297f..2702131441 100644 --- a/src/TunnelEncapsulation.h +++ b/src/TunnelEncapsulation.h @@ -249,6 +249,11 @@ public: return nullptr; } + /** + * Pops the last element off the encapsulation stack. + */ + void Pop(); + protected: std::vector* conns; }; diff --git a/src/packet_analysis/protocol/ieee802_11/IEEE802_11.cc b/src/packet_analysis/protocol/ieee802_11/IEEE802_11.cc index c0969ee2e0..e7e80a2545 100644 --- a/src/packet_analysis/protocol/ieee802_11/IEEE802_11.cc +++ b/src/packet_analysis/protocol/ieee802_11/IEEE802_11.cc @@ -17,6 +17,7 @@ bool IEEE802_11Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* } u_char fc_80211 = data[0]; // Frame Control field + bool is_amsdu = false; // Skip non-data frame types (management & control). if ( ! ((fc_80211 >> 2) & 0x02) ) @@ -33,9 +34,9 @@ bool IEEE802_11Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* // Look for the QoS indicator bit. if ( (fc_80211 >> 4) & 0x08 ) { - // Skip in case of A-MSDU subframes indicated by QoS control field. - if ( data[len_80211] & 0x80 ) - return false; + // Store off whether this is an A-MSDU header, which indicates that there are + // mulitple packets following the 802.11 header. + is_amsdu = (data[len_80211] & 0x80) == 0x80; // Check for the protected bit. This means the data is encrypted and we can't // do anything with it. @@ -75,13 +76,78 @@ bool IEEE802_11Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* break; } - // skip 802.11 data header + // skip the 802.11 data header data += len_80211; + len -= len_80211; - len_80211 += 8; - if ( len_80211 >= len ) + if ( ! is_amsdu ) { - Weird("truncated_802_11_header", packet); + return HandleInnerPacket(len, data, packet); + } + else + { + size_t amsdu_padding = 0; + size_t encap_index = packet->encap ? packet->encap->Depth() : 0; + + while ( len > 0 ) + { + if ( len < 14 ) + { + Weird("truncated_802_11_amsdu_header", packet); + return false; + } + + // This is the length of everything after the A-MSDU subframe header. + size_t amsdu_len = (data[12] << 8) + data[13]; + if ( len < amsdu_len ) + { + Weird("truncated_802_11_amsdu_packet", packet); + return false; + } + + // Skip the A-MSDU subframe header. This should place us at the start of an LLC header. + data += 14; + len -= 14; + + if ( ! HandleInnerPacket(amsdu_len, data, packet) ) + { + Weird("invalid_802_11_amsdu_inner_packet", packet); + return false; + } + + data += amsdu_len; + len -= amsdu_len; + + // Each A-MSDU subframe is padded by up to 3 bytes to make a multiple of 4. This padding + // isn't included in the length field value. The padding also doesn't happen with the + // last subframe, so check to see that we can even subtract it. Unfortunately, there + // isn't a frame counter in the header so we just have trust that it all works out. + amsdu_padding = amsdu_len % 4; + if ( len >= amsdu_padding ) + { + data += amsdu_padding; + len -= amsdu_padding; + } + + // Pop encapsuations back up to the level where we started processing so that the next + // subframe gets the same encapsulation stack. + if ( packet->encap ) + { + while ( packet->encap->Depth() > encap_index ) + packet->encap->Pop(); + } + } + + return true; + } + } + +bool IEEE802_11Analyzer::HandleInnerPacket(size_t len, const uint8_t* data, Packet* packet) const + { + // Make sure there's room for an LLC header. + if ( len < 8 ) + { + Weird("truncated_802_11_llc_header", packet); return false; } @@ -92,6 +158,7 @@ bool IEEE802_11Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* data[5] == 0 ) { data += 6; + len -= 6; } else { @@ -100,11 +167,13 @@ bool IEEE802_11Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* return false; } + // Get the protocol and skip the rest of the LLC header. uint32_t protocol = (data[0] << 8) + data[1]; data += 2; + len -= 2; if ( packet->tunnel_type == BifEnum::Tunnel::NONE ) - return ForwardPacket(len - len_80211, data, packet, protocol); + return ForwardPacket(len, data, packet, protocol); else { // For tunneled packets, reset the packet's protocol based on the one in the LLC header. @@ -114,6 +183,6 @@ bool IEEE802_11Analyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* else if ( protocol == 0x86DD ) packet->proto = IPPROTO_IPV6; - return ForwardPacket(len - len_80211, data, packet, packet->proto); + return ForwardPacket(len, data, packet, packet->proto); } } diff --git a/src/packet_analysis/protocol/ieee802_11/IEEE802_11.h b/src/packet_analysis/protocol/ieee802_11/IEEE802_11.h index 282c76bbaf..23307c3d27 100644 --- a/src/packet_analysis/protocol/ieee802_11/IEEE802_11.h +++ b/src/packet_analysis/protocol/ieee802_11/IEEE802_11.h @@ -20,6 +20,9 @@ public: { return std::make_shared(); } + +private: + bool HandleInnerPacket(size_t len, const uint8_t* data, Packet* packet) const; }; } diff --git a/testing/btest/Baseline/core.tunnels.gre-aruba-amsdu/conn.log b/testing/btest/Baseline/core.tunnels.gre-aruba-amsdu/conn.log new file mode 100644 index 0000000000..66e2c52380 --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gre-aruba-amsdu/conn.log @@ -0,0 +1,11 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig local_resp missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents +#types time string addr port addr port enum string interval count count string bool bool count string count count count count set[string] +XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 157.240.18.16 443 149.159.130.184 49392 tcp - - - - OTH F F 0 D 2 356 0 0 CHhAvVGS1DHFjwGM9 +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/core.tunnels.gre-aruba-amsdu/tunnel.log b/testing/btest/Baseline/core.tunnels.gre-aruba-amsdu/tunnel.log new file mode 100644 index 0000000000..a1529d17cf --- /dev/null +++ b/testing/btest/Baseline/core.tunnels.gre-aruba-amsdu/tunnel.log @@ -0,0 +1,11 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path tunnel +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action +#types time string addr port addr port enum enum +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 10.226.22.9 0 10.102.16.187 0 Tunnel::GRE Tunnel::DISCOVER +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Traces/tunnels/gre-aruba-amsdu.pcap b/testing/btest/Traces/tunnels/gre-aruba-amsdu.pcap new file mode 100644 index 0000000000000000000000000000000000000000..064d87bcc87af0abb22c358d8c5152825374e7c2 GIT binary patch literal 509 zcmca|c+)~A1{MYcU}0bca%?7jOL}I@%y1RR0bvG)I0i;W1}QnFe;XPZ7{oXjTp1V- zgT(*o*E4WE6654b6WGnb(B#m;#K4dy>S5#l+~M)HlrK{{9(=A}cYuMR0V)dNGb*lH z#SGL9Hb?SsxdTH8+bsUMAA|&^&Trbmxck6|$wDb&>(-vuXpmq!p}L#_Xgdej)_uy4 zI?ay=i!(DbJougNzsdXbjrVK9J4N>IFI-o+*O1ei{w?1P8bV_0|z9b3Ge{oM