From 2057ed8028b4a5c951ed5b6005c5088890c1e689 Mon Sep 17 00:00:00 2001 From: Marc Date: Wed, 12 Jan 2022 22:19:01 +0000 Subject: parse: Check frame minimum length when parsing Radiotap header --- src/libwifi/core/frame/frame.c | 2 +- src/libwifi/parse/misc/radiotap.c | 9 ++++++++- src/libwifi/parse/misc/radiotap.h | 7 +++++-- utils/src/test_parsing.c | 22 +++++++++++----------- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/libwifi/core/frame/frame.c b/src/libwifi/core/frame/frame.c index b4f50ad..78fe069 100644 --- a/src/libwifi/core/frame/frame.c +++ b/src/libwifi/core/frame/frame.c @@ -42,7 +42,7 @@ int libwifi_get_wifi_frame(struct libwifi_frame *fi, const unsigned char *frame, if (radiotap) { struct libwifi_radiotap_info rtap_info = {0}; - libwifi_parse_radiotap_info(&rtap_info, frame_data); + libwifi_parse_radiotap_info(&rtap_info, frame_data, frame_len); // Skip forward by the length of the radiotap header frame_data_len -= rtap_info.length; diff --git a/src/libwifi/parse/misc/radiotap.c b/src/libwifi/parse/misc/radiotap.c index 176167e..80ddced 100644 --- a/src/libwifi/parse/misc/radiotap.c +++ b/src/libwifi/parse/misc/radiotap.c @@ -16,6 +16,7 @@ #include "radiotap.h" #include "../../core/radiotap/radiotap_iter.h" +#include #include #include @@ -23,9 +24,13 @@ * The libwifi radiotap parser uses the usual ieee80211_radiotap_iterator to parse incoming * radiotap headers into a consumable libwifi_radiotap_info struct. */ -void libwifi_parse_radiotap_info(struct libwifi_radiotap_info *info, const unsigned char *frame) { +int libwifi_parse_radiotap_info(struct libwifi_radiotap_info *info, const unsigned char *frame, size_t frame_len) { memset(info, 0, sizeof(struct libwifi_radiotap_info)); + if (frame_len < sizeof(struct ieee80211_radiotap_header)) { + return -EINVAL; + } + struct ieee80211_radiotap_header *rh = (struct ieee80211_radiotap_header *) frame; struct ieee80211_radiotap_iterator it = {0}; int ret = ieee80211_radiotap_iterator_init(&it, (void *) frame, rh->it_len, NULL); @@ -99,6 +104,8 @@ void libwifi_parse_radiotap_info(struct libwifi_radiotap_info *info, const unsig ret = ieee80211_radiotap_iterator_next(&it); } + + return 0; } /** diff --git a/src/libwifi/parse/misc/radiotap.h b/src/libwifi/parse/misc/radiotap.h index 8f74e6a..d57a760 100644 --- a/src/libwifi/parse/misc/radiotap.h +++ b/src/libwifi/parse/misc/radiotap.h @@ -17,6 +17,7 @@ #define LIBWIFI_PARSE_RADIOTAP_H #include "../../core/misc/radiotap.h" +#include #include /** @@ -25,8 +26,10 @@ * * @param info A libwifi_radiotap_info * @param frame A raw 802.11 frame - */ -void libwifi_parse_radiotap_info(struct libwifi_radiotap_info *info, const unsigned char *frame); + * @param frame_len Length of the given 802.11 frame + * @returns Negative errno on error, 0 on success +*/ +int libwifi_parse_radiotap_info(struct libwifi_radiotap_info *info, const unsigned char *frame, size_t frame_len); /** * Retrieve the signal strength from a raw frame via radiotap header. diff --git a/utils/src/test_parsing.c b/utils/src/test_parsing.c index 293fbb0..339816e 100644 --- a/utils/src/test_parsing.c +++ b/utils/src/test_parsing.c @@ -132,9 +132,9 @@ void print_tag_info(unsigned char *data, size_t data_len) { } while (libwifi_tag_iterator_next(&it) != -1); } -void parse_radiotap(const unsigned char *packet) { +void parse_radiotap(const unsigned char *packet, size_t packet_len) { struct libwifi_radiotap_info rtap_info; - libwifi_parse_radiotap_info(&rtap_info, packet); + libwifi_parse_radiotap_info(&rtap_info, packet, packet_len); printf("=== Radiotap Parsing ===\n"); printf("Radiotap Channel: %d\n", rtap_info.channel.freq); @@ -166,7 +166,7 @@ void parse_beacon(struct libwifi_frame frame, unsigned char *args, const struct } if (got_radiotap && parse_radiotap_header) { - parse_radiotap(packet); + parse_radiotap(packet, header->caplen); } print_bss_info(&bss); @@ -184,7 +184,7 @@ void parse_probe_request(struct libwifi_frame frame, unsigned char *args, const } if (got_radiotap && parse_radiotap_header) { - parse_radiotap(packet); + parse_radiotap(packet, header->caplen); } print_sta_info(&sta); @@ -201,7 +201,7 @@ void parse_probe_response(struct libwifi_frame frame, unsigned char *args, const } if (got_radiotap && parse_radiotap_header) { - parse_radiotap(packet); + parse_radiotap(packet, header->caplen); } print_bss_info(&bss); @@ -219,7 +219,7 @@ void parse_deauth(struct libwifi_frame frame, unsigned char *args, const struct } if (got_radiotap && parse_radiotap_header) { - parse_radiotap(packet); + parse_radiotap(packet, header->caplen); } printf("=== Deauthentication Frame ===\n"); @@ -258,7 +258,7 @@ void parse_disassoc(struct libwifi_frame frame, unsigned char *args, const struc } if (got_radiotap && parse_radiotap_header) { - parse_radiotap(packet); + parse_radiotap(packet, header->caplen); } printf("=== Disassociation Frame ===\n"); @@ -296,7 +296,7 @@ void parse_assoc_request(struct libwifi_frame frame, unsigned char *args, const } if (got_radiotap && parse_radiotap_header) { - parse_radiotap(packet); + parse_radiotap(packet, header->caplen); } print_sta_info(&sta); @@ -313,7 +313,7 @@ void parse_assoc_response(struct libwifi_frame frame, unsigned char *args, const } if (got_radiotap && parse_radiotap_header) { - parse_radiotap(packet); + parse_radiotap(packet, header->caplen); } print_bss_info(&bss); @@ -330,7 +330,7 @@ void parse_reassoc_request(struct libwifi_frame frame, unsigned char *args, cons } if (got_radiotap && parse_radiotap_header) { - parse_radiotap(packet); + parse_radiotap(packet, header->caplen); } print_sta_info(&sta); @@ -347,7 +347,7 @@ void parse_reassoc_response(struct libwifi_frame frame, unsigned char *args, con } if (got_radiotap && parse_radiotap_header) { - parse_radiotap(packet); + parse_radiotap(packet, header->caplen); } print_bss_info(&bss); -- cgit 1.4.1