]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
GAS client: Use Protected Dual of Public Action frames with PMF
authorJouni Malinen <jouni@qca.qualcomm.com>
Thu, 23 Jan 2014 09:18:20 +0000 (11:18 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 23 Jan 2014 09:50:28 +0000 (11:50 +0200)
When GAS is used with PMF negotiated, Protected Dual of Public Action
frames are expected to be used instead of Public Action frames, i.e.,
the GAS/ANQP frames are expected to be encrypted. Conver Public Action
GAS queries to use Dual of Public Action frame if PMF has been
negotiated with the AP to which the frame is being sent.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

src/drivers/driver_nl80211.c
wpa_supplicant/events.c
wpa_supplicant/gas_query.c
wpa_supplicant/gas_query.h

index e648486fd743287003b4f583719296322a606ecc..b5bf368dd84562f1dc284f8313716fcd21a58c48 100644 (file)
@@ -4216,6 +4216,18 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
        /* GAS Comeback Response */
        if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0d", 2) < 0)
                ret = -1;
+       /* Protected GAS Initial Request */
+       if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0a", 2) < 0)
+               ret = -1;
+       /* Protected GAS Initial Response */
+       if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0b", 2) < 0)
+               ret = -1;
+       /* Protected GAS Comeback Request */
+       if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0c", 2) < 0)
+               ret = -1;
+       /* Protected GAS Comeback Response */
+       if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0d", 2) < 0)
+               ret = -1;
 #endif /* CONFIG_P2P || CONFIG_INTERWORKING */
 #ifdef CONFIG_P2P
        /* P2P Public Action */
index 862ebb000ac78e11bada33e7050496cc9d286ed7..d9449fdb79d857dbf1e31c8cccb9e4b8c4eade41 100644 (file)
@@ -2735,8 +2735,10 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
 #endif /* CONFIG_WNM */
 
 #ifdef CONFIG_GAS
-       if (mgmt->u.action.category == WLAN_ACTION_PUBLIC &&
+       if ((mgmt->u.action.category == WLAN_ACTION_PUBLIC ||
+            mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL) &&
            gas_query_rx(wpa_s->gas, mgmt->da, mgmt->sa, mgmt->bssid,
+                        mgmt->u.action.category,
                         payload, plen, freq) == 0)
                return;
 #endif /* CONFIG_GAS */
index f002fd50960d3639609b859e3177a432c08c4796..abcb391a14c9b5964eadec63b99152da034f6459 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Generic advertisement service (GAS) query
  * Copyright (c) 2009, Atheros Communications
- * Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
+ * Copyright (c) 2011-2014, Qualcomm Atheros, Inc.
  * Copyright (c) 2011-2014, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
@@ -15,6 +15,7 @@
 #include "common/ieee802_11_defs.h"
 #include "common/gas.h"
 #include "common/wpa_ctrl.h"
+#include "rsn_supp/wpa.h"
 #include "wpa_supplicant_i.h"
 #include "driver_i.h"
 #include "offchannel.h"
@@ -228,13 +229,28 @@ static void gas_query_tx_status(struct wpa_supplicant *wpa_s,
 }
 
 
+static int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
+{
+       if (wpa_s->current_ssid == NULL ||
+           wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
+           os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
+               return 0;
+       return wpa_sm_pmf_enabled(wpa_s->wpa);
+}
+
+
 static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query,
                        struct wpabuf *req)
 {
-       int res;
+       int res, prot = pmf_in_use(gas->wpa_s, query->addr);
+
        wpa_printf(MSG_DEBUG, "GAS: Send action frame to " MACSTR " len=%u "
-                  "freq=%d", MAC2STR(query->addr),
-                  (unsigned int) wpabuf_len(req), query->freq);
+                  "freq=%d prot=%d", MAC2STR(query->addr),
+                  (unsigned int) wpabuf_len(req), query->freq, prot);
+       if (prot) {
+               u8 *categ = wpabuf_mhead_u8(req);
+               *categ = WLAN_ACTION_PROTECTED_DUAL;
+       }
        res = offchannel_send_action(gas->wpa_s, query->freq, query->addr,
                                     gas->wpa_s->own_addr, query->addr,
                                     wpabuf_head(req), wpabuf_len(req), 1000,
@@ -386,27 +402,41 @@ static void gas_query_rx_comeback(struct gas_query *gas,
 
 
 /**
- * gas_query_rx - Indicate reception of a Public Action frame
+ * gas_query_rx - Indicate reception of a Public Action or Protected Dual frame
  * @gas: GAS query data from gas_query_init()
  * @da: Destination MAC address of the Action frame
  * @sa: Source MAC address of the Action frame
  * @bssid: BSSID of the Action frame
+ * @categ: Category of the Action frame
  * @data: Payload of the Action frame
  * @len: Length of @data
  * @freq: Frequency (in MHz) on which the frame was received
  * Returns: 0 if the Public Action frame was a GAS frame or -1 if not
  */
 int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
-                const u8 *bssid, const u8 *data, size_t len, int freq)
+                const u8 *bssid, u8 categ, const u8 *data, size_t len,
+                int freq)
 {
        struct gas_query_pending *query;
        u8 action, dialog_token, frag_id = 0, more_frags = 0;
        u16 comeback_delay, resp_len;
        const u8 *pos, *adv_proto;
+       int prot, pmf;
 
        if (gas == NULL || len < 4)
                return -1;
 
+       prot = categ == WLAN_ACTION_PROTECTED_DUAL;
+       pmf = pmf_in_use(gas->wpa_s, bssid);
+       if (prot && !pmf) {
+               wpa_printf(MSG_DEBUG, "GAS: Drop unexpected protected GAS frame when PMF is disabled");
+               return 0;
+       }
+       if (!prot && pmf) {
+               wpa_printf(MSG_DEBUG, "GAS: Drop unexpected unprotected GAS frame when PMF is enabled");
+               return 0;
+       }
+
        pos = data;
        action = *pos++;
        dialog_token = *pos++;
index 5c3d161adfb15210aac288511cee93412bad0e3a..ad1349088ee1f2581e37ff7f3cac4dc7220ae2a7 100644 (file)
@@ -17,7 +17,8 @@ struct gas_query;
 struct gas_query * gas_query_init(struct wpa_supplicant *wpa_s);
 void gas_query_deinit(struct gas_query *gas);
 int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
-                const u8 *bssid, const u8 *data, size_t len, int freq);
+                const u8 *bssid, u8 categ, const u8 *data, size_t len,
+                int freq);
 
 /**
  * enum gas_query_result - GAS query result