GAS client: Use Protected Dual of Public Action frames with PMF
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>
This commit is contained in:
parent
5ce00d09c0
commit
c5a64e2d51
4 changed files with 53 additions and 8 deletions
|
@ -4216,6 +4216,18 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
|
||||||
/* GAS Comeback Response */
|
/* GAS Comeback Response */
|
||||||
if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0d", 2) < 0)
|
if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0d", 2) < 0)
|
||||||
ret = -1;
|
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 */
|
#endif /* CONFIG_P2P || CONFIG_INTERWORKING */
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
/* P2P Public Action */
|
/* P2P Public Action */
|
||||||
|
|
|
@ -2735,8 +2735,10 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
|
||||||
#endif /* CONFIG_WNM */
|
#endif /* CONFIG_WNM */
|
||||||
|
|
||||||
#ifdef CONFIG_GAS
|
#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,
|
gas_query_rx(wpa_s->gas, mgmt->da, mgmt->sa, mgmt->bssid,
|
||||||
|
mgmt->u.action.category,
|
||||||
payload, plen, freq) == 0)
|
payload, plen, freq) == 0)
|
||||||
return;
|
return;
|
||||||
#endif /* CONFIG_GAS */
|
#endif /* CONFIG_GAS */
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Generic advertisement service (GAS) query
|
* Generic advertisement service (GAS) query
|
||||||
* Copyright (c) 2009, Atheros Communications
|
* 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>
|
* Copyright (c) 2011-2014, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
@ -15,6 +15,7 @@
|
||||||
#include "common/ieee802_11_defs.h"
|
#include "common/ieee802_11_defs.h"
|
||||||
#include "common/gas.h"
|
#include "common/gas.h"
|
||||||
#include "common/wpa_ctrl.h"
|
#include "common/wpa_ctrl.h"
|
||||||
|
#include "rsn_supp/wpa.h"
|
||||||
#include "wpa_supplicant_i.h"
|
#include "wpa_supplicant_i.h"
|
||||||
#include "driver_i.h"
|
#include "driver_i.h"
|
||||||
#include "offchannel.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,
|
static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query,
|
||||||
struct wpabuf *req)
|
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 "
|
wpa_printf(MSG_DEBUG, "GAS: Send action frame to " MACSTR " len=%u "
|
||||||
"freq=%d", MAC2STR(query->addr),
|
"freq=%d prot=%d", MAC2STR(query->addr),
|
||||||
(unsigned int) wpabuf_len(req), query->freq);
|
(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,
|
res = offchannel_send_action(gas->wpa_s, query->freq, query->addr,
|
||||||
gas->wpa_s->own_addr, query->addr,
|
gas->wpa_s->own_addr, query->addr,
|
||||||
wpabuf_head(req), wpabuf_len(req), 1000,
|
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()
|
* @gas: GAS query data from gas_query_init()
|
||||||
* @da: Destination MAC address of the Action frame
|
* @da: Destination MAC address of the Action frame
|
||||||
* @sa: Source MAC address of the Action frame
|
* @sa: Source MAC address of the Action frame
|
||||||
* @bssid: BSSID of the Action frame
|
* @bssid: BSSID of the Action frame
|
||||||
|
* @categ: Category of the Action frame
|
||||||
* @data: Payload of the Action frame
|
* @data: Payload of the Action frame
|
||||||
* @len: Length of @data
|
* @len: Length of @data
|
||||||
* @freq: Frequency (in MHz) on which the frame was received
|
* @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
|
* 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,
|
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;
|
struct gas_query_pending *query;
|
||||||
u8 action, dialog_token, frag_id = 0, more_frags = 0;
|
u8 action, dialog_token, frag_id = 0, more_frags = 0;
|
||||||
u16 comeback_delay, resp_len;
|
u16 comeback_delay, resp_len;
|
||||||
const u8 *pos, *adv_proto;
|
const u8 *pos, *adv_proto;
|
||||||
|
int prot, pmf;
|
||||||
|
|
||||||
if (gas == NULL || len < 4)
|
if (gas == NULL || len < 4)
|
||||||
return -1;
|
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;
|
pos = data;
|
||||||
action = *pos++;
|
action = *pos++;
|
||||||
dialog_token = *pos++;
|
dialog_token = *pos++;
|
||||||
|
|
|
@ -17,7 +17,8 @@ struct gas_query;
|
||||||
struct gas_query * gas_query_init(struct wpa_supplicant *wpa_s);
|
struct gas_query * gas_query_init(struct wpa_supplicant *wpa_s);
|
||||||
void gas_query_deinit(struct gas_query *gas);
|
void gas_query_deinit(struct gas_query *gas);
|
||||||
int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
|
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
|
* enum gas_query_result - GAS query result
|
||||||
|
|
Loading…
Reference in a new issue