wlantest: Verify that unicast robust mgmt frames are protected

This commit is contained in:
Jouni Malinen 2010-11-12 23:17:20 +02:00
parent 070d6173e2
commit 2102ecf0b5

View file

@ -440,7 +440,7 @@ static void rx_mgmt_disassoc(struct wlantest *wt, const u8 *data, size_t len,
static void rx_mgmt_action_sa_query(struct wlantest *wt, static void rx_mgmt_action_sa_query(struct wlantest *wt,
struct wlantest_sta *sta, struct wlantest_sta *sta,
const struct ieee80211_mgmt *mgmt, const struct ieee80211_mgmt *mgmt,
size_t len) size_t len, int valid)
{ {
const u8 *rx_id; const u8 *rx_id;
u8 *id; u8 *id;
@ -468,9 +468,10 @@ static void rx_mgmt_action_sa_query(struct wlantest *wt,
else else
id = sta->sta_sa_query_tr; id = sta->sta_sa_query_tr;
wpa_printf(MSG_INFO, "SA Query Request " MACSTR " -> " MACSTR wpa_printf(MSG_INFO, "SA Query Request " MACSTR " -> " MACSTR
" (trans_id=%02x%02x)", " (trans_id=%02x%02x)%s",
MAC2STR(mgmt->sa), MAC2STR(mgmt->da), MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
rx_id[0], rx_id[1]); rx_id[0], rx_id[1],
valid ? "" : " (invalid protection)");
os_memcpy(id, mgmt->u.action.u.sa_query_req.trans_id, 2); os_memcpy(id, mgmt->u.action.u.sa_query_req.trans_id, 2);
break; break;
case WLAN_SA_QUERY_RESPONSE: case WLAN_SA_QUERY_RESPONSE:
@ -480,11 +481,12 @@ static void rx_mgmt_action_sa_query(struct wlantest *wt,
else else
id = sta->ap_sa_query_tr; id = sta->ap_sa_query_tr;
wpa_printf(MSG_INFO, "SA Query Response " MACSTR " -> " MACSTR wpa_printf(MSG_INFO, "SA Query Response " MACSTR " -> " MACSTR
" (trans_id=%02x%02x; %s)", " (trans_id=%02x%02x; %s)%s",
MAC2STR(mgmt->sa), MAC2STR(mgmt->da), MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
rx_id[0], rx_id[1], rx_id[0], rx_id[1],
os_memcmp(rx_id, id, 2) == 0 ? os_memcmp(rx_id, id, 2) == 0 ?
"match" : "mismatch"); "match" : "mismatch",
valid ? "" : " (invalid protection)");
break; break;
default: default:
wpa_printf(MSG_INFO, "Unexpected SA Query action value %u " wpa_printf(MSG_INFO, "Unexpected SA Query action value %u "
@ -495,7 +497,8 @@ static void rx_mgmt_action_sa_query(struct wlantest *wt,
} }
static void rx_mgmt_action(struct wlantest *wt, const u8 *data, size_t len) static void rx_mgmt_action(struct wlantest *wt, const u8 *data, size_t len,
int valid)
{ {
const struct ieee80211_mgmt *mgmt; const struct ieee80211_mgmt *mgmt;
struct wlantest_bss *bss; struct wlantest_bss *bss;
@ -521,9 +524,9 @@ static void rx_mgmt_action(struct wlantest *wt, const u8 *data, size_t len)
} }
wpa_printf(MSG_DEBUG, "ACTION " MACSTR " -> " MACSTR wpa_printf(MSG_DEBUG, "ACTION " MACSTR " -> " MACSTR
" (category=%u)", " (category=%u) (valid=%d)",
MAC2STR(mgmt->sa), MAC2STR(mgmt->da), MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
mgmt->u.action.category); mgmt->u.action.category, valid);
wpa_hexdump(MSG_MSGDUMP, "ACTION payload", data + 24, len - 24); wpa_hexdump(MSG_MSGDUMP, "ACTION payload", data + 24, len - 24);
if (mgmt->u.action.category != WLAN_ACTION_PUBLIC && if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
@ -535,7 +538,7 @@ static void rx_mgmt_action(struct wlantest *wt, const u8 *data, size_t len)
switch (mgmt->u.action.category) { switch (mgmt->u.action.category) {
case WLAN_ACTION_SA_QUERY: case WLAN_ACTION_SA_QUERY:
rx_mgmt_action_sa_query(wt, sta, mgmt, len); rx_mgmt_action_sa_query(wt, sta, mgmt, len, valid);
break; break;
} }
} }
@ -710,6 +713,43 @@ static u8 * mgmt_ccmp_decrypt(struct wlantest *wt, const u8 *data, size_t len,
} }
static int check_mgmt_ccmp(struct wlantest *wt, const u8 *data, size_t len)
{
const struct ieee80211_mgmt *mgmt;
u16 fc;
struct wlantest_bss *bss;
struct wlantest_sta *sta;
mgmt = (const struct ieee80211_mgmt *) data;
fc = le_to_host16(mgmt->frame_control);
if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
if (len > 24 &&
mgmt->u.action.category == WLAN_ACTION_PUBLIC)
return 0; /* Not a robust management frame */
}
bss = bss_get(wt, mgmt->bssid);
if (bss == NULL)
return 0;
if (os_memcmp(mgmt->da, mgmt->bssid, ETH_ALEN) == 0)
sta = sta_get(bss, mgmt->sa);
else
sta = sta_get(bss, mgmt->da);
if (sta == NULL)
return 0;
if (sta->rsn_capab & WPA_CAPABILITY_MFPC) {
wpa_printf(MSG_INFO, "Robust individually-addressed "
"management frame sent without CCMP by "
MACSTR, MAC2STR(mgmt->sa));
return -1;
}
return 0;
}
void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len) void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len)
{ {
const struct ieee80211_hdr *hdr; const struct ieee80211_hdr *hdr;
@ -729,8 +769,10 @@ void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len)
if ((hdr->addr1[0] & 0x01) && if ((hdr->addr1[0] & 0x01) &&
(stype == WLAN_FC_STYPE_DEAUTH || (stype == WLAN_FC_STYPE_DEAUTH ||
stype == WLAN_FC_STYPE_DISASSOC || stype == WLAN_FC_STYPE_DISASSOC ||
stype == WLAN_FC_STYPE_ACTION)) stype == WLAN_FC_STYPE_ACTION)) {
check_bip(wt, data, len); if (check_bip(wt, data, len) < 0)
valid = 0;
}
wpa_printf((stype == WLAN_FC_STYPE_BEACON || wpa_printf((stype == WLAN_FC_STYPE_BEACON ||
stype == WLAN_FC_STYPE_PROBE_RESP || stype == WLAN_FC_STYPE_PROBE_RESP ||
@ -757,8 +799,14 @@ void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len)
valid = 0; valid = 0;
} }
/* TODO: verify that robust management frames are protected if MFP was if (!(fc & WLAN_FC_ISWEP) &&
* negotiated */ !(hdr->addr1[0] & 0x01) &&
(stype == WLAN_FC_STYPE_DEAUTH ||
stype == WLAN_FC_STYPE_DISASSOC ||
stype == WLAN_FC_STYPE_ACTION)) {
if (check_mgmt_ccmp(wt, data, len) < 0)
valid = 0;
}
switch (stype) { switch (stype) {
case WLAN_FC_STYPE_BEACON: case WLAN_FC_STYPE_BEACON:
@ -789,8 +837,7 @@ void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len)
rx_mgmt_disassoc(wt, data, len, valid); rx_mgmt_disassoc(wt, data, len, valid);
break; break;
case WLAN_FC_STYPE_ACTION: case WLAN_FC_STYPE_ACTION:
if (valid) rx_mgmt_action(wt, data, len, valid);
rx_mgmt_action(wt, data, len);
break; break;
} }