From 0570a3ea7d87bd106d557ebdf3a321d1bf61d04c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 5 Dec 2014 00:56:05 +0200 Subject: [PATCH] HS 2.0: Clarify OSU Provider list length validation The previous version was somewhat too complex for some static analyzers. Use local variables for the extracted length fields and explicitly compare these against the remaining buffer length. (CID 68121) Signed-off-by: Jouni Malinen --- wpa_supplicant/hs20_supplicant.c | 59 ++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c index 315fa284c..d91a93627 100644 --- a/wpa_supplicant/hs20_supplicant.c +++ b/wpa_supplicant/hs20_supplicant.c @@ -562,7 +562,7 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, const u8 *end = pos + len; u16 len2; const u8 *pos2; - u8 uri_len; + u8 uri_len, osu_method_len, osu_nai_len; wpa_hexdump(MSG_DEBUG, "HS 2.0: Parsing OSU Provider", pos, len); prov = os_realloc_array(wpa_s->osu_prov, @@ -586,7 +586,7 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, } len2 = WPA_GET_LE16(pos); pos += 2; - if (pos + len2 > end) { + if (len2 > end - pos) { wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU " "Friendly Name Duples"); return; @@ -623,13 +623,19 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, pos += uri_len; /* OSU Method list */ - if (pos + 1 > end || pos + 1 + pos[0] > end) { + if (pos + 1 > end) { + wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Method " + "list length"); + return; + } + osu_method_len = pos[0]; + if (osu_method_len > end - pos - 1) { wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Method " "list"); return; } pos2 = pos + 1; - pos += 1 + pos[0]; + pos += 1 + osu_method_len; while (pos2 < pos) { if (*pos2 < 32) prov->osu_methods |= BIT(*pos2); @@ -644,7 +650,7 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, } len2 = WPA_GET_LE16(pos); pos += 2; - if (pos + len2 > end) { + if (len2 > end - pos) { wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for Icons " "Available"); return; @@ -655,6 +661,8 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, /* Icons Available */ while (pos2 < pos) { struct osu_icon *icon = &prov->icon[prov->icon_count]; + u8 flen; + if (pos2 + 2 + 2 + 3 + 1 + 1 > pos) { wpa_printf(MSG_DEBUG, "HS 2.0: Invalid Icon Metadata"); break; @@ -667,31 +675,43 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, os_memcpy(icon->lang, pos2, 3); pos2 += 3; - if (pos2 + 1 + pos2[0] > pos) { + flen = pos2[0]; + if (flen > pos - pos2 - 1) { wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon Type"); break; } - os_memcpy(icon->icon_type, pos2 + 1, pos2[0]); - pos2 += 1 + pos2[0]; + os_memcpy(icon->icon_type, pos2 + 1, flen); + pos2 += 1 + flen; - if (pos2 + 1 + pos2[0] > pos) { + if (pos2 + 1 > pos) { + wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon " + "Filename length"); + break; + } + flen = pos2[0]; + if (flen > pos - pos2 - 1) { wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon " "Filename"); break; } - os_memcpy(icon->filename, pos2 + 1, pos2[0]); - pos2 += 1 + pos2[0]; + os_memcpy(icon->filename, pos2 + 1, flen); + pos2 += 1 + flen; prov->icon_count++; } /* OSU_NAI */ - if (pos + 1 > end || pos + 1 + pos[0] > end) { + if (pos + 1 > end) { wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU_NAI"); return; } - os_memcpy(prov->osu_nai, pos + 1, pos[0]); - pos += 1 + pos[0]; + osu_nai_len = pos[0]; + if (osu_nai_len > end - pos - 1) { + wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU_NAI"); + return; + } + os_memcpy(prov->osu_nai, pos + 1, osu_nai_len); + pos += 1 + osu_nai_len; /* OSU Service Description Length */ if (pos + 2 > end) { @@ -701,7 +721,7 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, } len2 = WPA_GET_LE16(pos); pos += 2; - if (pos + len2 > end) { + if (len2 > end - pos) { wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU " "Service Description Duples"); return; @@ -712,15 +732,18 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, /* OSU Service Description Duples */ while (pos2 + 4 <= pos && prov->serv_desc_count < OSU_MAX_ITEMS) { struct osu_lang_string *f; - if (pos2 + 1 + pos2[0] > pos || pos2[0] < 3) { + u8 descr_len; + + descr_len = pos2[0]; + if (descr_len > pos - pos2 - 1 || descr_len < 3) { wpa_printf(MSG_DEBUG, "Invalid OSU Service " "Description"); break; } f = &prov->serv_desc[prov->serv_desc_count++]; os_memcpy(f->lang, pos2 + 1, 3); - os_memcpy(f->text, pos2 + 1 + 3, pos2[0] - 3); - pos2 += 1 + pos2[0]; + os_memcpy(f->text, pos2 + 1 + 3, descr_len - 3); + pos2 += 1 + descr_len; } wpa_printf(MSG_DEBUG, "HS 2.0: Added OSU Provider through " MACSTR,