TDLS: Do not allow setup to be started if AP prohibits TDLS

master
Jouni Malinen 14 years ago committed by Jouni Malinen
parent fb12d186b6
commit 52c9e6f3f5

@ -1168,6 +1168,7 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
u8 dtoken;
u16 ielen;
u16 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
int tdls_prohibited = sm->tdls_prohibited;
if (len < 3 + 3)
return -1;
@ -1226,6 +1227,12 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
}
#endif /* CONFIG_TDLS_TESTING */
if (tdls_prohibited) {
wpa_printf(MSG_INFO, "TDLS: TDLS prohibited in this BSS");
status = WLAN_STATUS_REQUEST_DECLINED;
goto error;
}
if (!wpa_tdls_get_privacy(sm)) {
if (kde.rsn_ie) {
wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M1 while "
@ -1808,6 +1815,13 @@ static u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs)
int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr)
{
struct wpa_tdls_peer *peer;
int tdls_prohibited = sm->tdls_prohibited;
if (tdls_prohibited) {
wpa_printf(MSG_DEBUG, "TDLS: TDLS is prohibited in this BSS - "
"reject request to start setup");
return -1;
}
/* Find existing entry and if found, use that instead of adding
* a new one */
@ -1984,3 +1998,39 @@ void wpa_tdls_disassoc(struct wpa_sm *sm)
wpa_printf(MSG_DEBUG, "TDLS: Remove peers on disassociation");
wpa_tdls_remove_peers(sm);
}
static int wpa_tdls_prohibited(const u8 *ies, size_t len)
{
struct wpa_eapol_ie_parse elems;
if (ies == NULL)
return 0;
if (wpa_supplicant_parse_ies(ies, len, &elems) < 0)
return 0;
if (elems.ext_capab == NULL || elems.ext_capab_len < 2 + 5)
return 0;
/* bit 38 - TDLS Prohibited */
return !!(elems.ext_capab[2 + 4] & 0x40);
}
void wpa_tdls_ap_ies(struct wpa_sm *sm, const u8 *ies, size_t len)
{
sm->tdls_prohibited = wpa_tdls_prohibited(ies, len);
wpa_printf(MSG_DEBUG, "TDLS: TDLS is %s in the target BSS",
sm->tdls_prohibited ? "prohibited" : "allowed");
}
void wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len)
{
if (!sm->tdls_prohibited && wpa_tdls_prohibited(ies, len)) {
wpa_printf(MSG_DEBUG, "TDLS: TDLS prohibited based on "
"(Re)Association Response IEs");
sm->tdls_prohibited = 1;
}
}

@ -338,6 +338,8 @@ wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
/* tdls.c */
void wpa_tdls_ap_ies(struct wpa_sm *sm, const u8 *ies, size_t len);
void wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len);
int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr);
int wpa_tdls_reneg(struct wpa_sm *sm, const u8 *addr);
int wpa_tdls_recv_teardown_notify(struct wpa_sm *sm, const u8 *addr,

@ -96,6 +96,7 @@ struct wpa_sm {
#endif /* CONFIG_PEERKEY */
#ifdef CONFIG_TDLS
struct wpa_tdls_peer *tdls;
int tdls_prohibited;
#endif /* CONFIG_TDLS */
#ifdef CONFIG_IEEE80211R

@ -426,6 +426,9 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
} else if (*pos == WLAN_EID_LINK_ID) {
ie->lnkid = pos;
ie->lnkid_len = pos[1] + 2;
} else if (*pos == WLAN_EID_EXT_CAPAB) {
ie->ext_capab = pos;
ie->ext_capab_len = pos[1] + 2;
} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
ret = wpa_parse_generic(pos, end, ie);
if (ret < 0)

@ -49,6 +49,8 @@ struct wpa_eapol_ie_parse {
const u8 *key_lifetime;
const u8 *lnkid;
size_t lnkid_len;
const u8 *ext_capab;
size_t ext_capab_len;
};
int wpa_supplicant_parse_ies(const u8 *buf, size_t len,

@ -1024,9 +1024,14 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
if (data->assoc_info.req_ies)
wpa_hexdump(MSG_DEBUG, "req_ies", data->assoc_info.req_ies,
data->assoc_info.req_ies_len);
if (data->assoc_info.resp_ies)
if (data->assoc_info.resp_ies) {
wpa_hexdump(MSG_DEBUG, "resp_ies", data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len);
#ifdef CONFIG_TDLS
wpa_tdls_assoc_resp_ies(wpa_s->wpa, data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len);
#endif /* CONFIG_TDLS */
}
if (data->assoc_info.beacon_ies)
wpa_hexdump(MSG_DEBUG, "beacon_ies",
data->assoc_info.beacon_ies,

@ -1046,6 +1046,10 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
return;
}
#ifdef CONFIG_TDLS
wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1), bss->ie_len);
#endif /* CONFIG_TDLS */
if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
ssid->mode == IEEE80211_MODE_INFRA) {
sme_authenticate(wpa_s, bss, ssid);

Loading…
Cancel
Save