]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
TDLS: Do not allow setup to be started if AP prohibits TDLS
authorJouni Malinen <jouni.malinen@atheros.com>
Fri, 28 Jan 2011 17:27:28 +0000 (19:27 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 6 Mar 2011 12:54:49 +0000 (14:54 +0200)
src/rsn_supp/tdls.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_i.h
src/rsn_supp/wpa_ie.c
src/rsn_supp/wpa_ie.h
wpa_supplicant/events.c
wpa_supplicant/wpa_supplicant.c

index 125ae084843a7149235539487018e624a3876536..a6e7f952a98b2ce054cafee7b7e1c3cbb9828d17 100644 (file)
@@ -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;
+       }
+}
index f14062b8f05a120bd16890d34dbd560677a86fcc..41bafee6317804abf3c3b799976852b4359280c4 100644 (file)
@@ -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,
index b8bb6286d7c6abe3fe28ef53ad9d73a012745a86..590dea149125601b43ddd1ed1148b4f4e8a6fd28 100644 (file)
@@ -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
index 5db6f097cdf809d78524f59ef0bbaacf4abea023..654cc1f1534096755265694c59d7097ff1476957 100644 (file)
@@ -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)
index 62a2677e8a254462de1da751c4bf514873a8d492..f939b13d1e7437d4588dfe6d374c9e4060a69b93 100644 (file)
@@ -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,
index 5105955b5d9fbe31ef4ba66f642f8717d009db40..1704e06704dd25434ee5b9ba100697ff5648ba99 100644 (file)
@@ -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,
index 34798791ce6694da7eee2db6786a02157c9f904c..60cda697f703ac20580d62aadb0d5a9380ec861b 100644 (file)
@@ -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);