mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-28 18:28:23 -05:00
GAS server: Add support for Protected Dual of Public Action frames
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. Add support for this different category of Action frames being used for GAS. The payload after the Category field is identical, so the only change is in using the Category field based on what was received in the request frames. For backwards compatibility, do not enforce protected dual to be used on the AP side, i.e., follow what the station does. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
e24fe94126
commit
5ce00d09c0
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generic advertisement service (GAS) server
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2011-2014, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
@ -19,6 +19,13 @@
|
||||
#include "gas_serv.h"
|
||||
|
||||
|
||||
static void convert_to_protected_dual(struct wpabuf *msg)
|
||||
{
|
||||
u8 *categ = wpabuf_mhead_u8(msg);
|
||||
*categ = WLAN_ACTION_PROTECTED_DUAL;
|
||||
}
|
||||
|
||||
|
||||
static struct gas_dialog_info *
|
||||
gas_dialog_create(struct hostapd_data *hapd, const u8 *addr, u8 dialog_token)
|
||||
{
|
||||
@ -774,7 +781,7 @@ static void rx_anqp_vendor_specific(struct hostapd_data *hapd,
|
||||
|
||||
static void gas_serv_req_local_processing(struct hostapd_data *hapd,
|
||||
const u8 *sa, u8 dialog_token,
|
||||
struct anqp_query_info *qi)
|
||||
struct anqp_query_info *qi, int prot)
|
||||
{
|
||||
struct wpabuf *buf, *tx_buf;
|
||||
|
||||
@ -806,6 +813,7 @@ static void gas_serv_req_local_processing(struct hostapd_data *hapd,
|
||||
wpabuf_free(buf);
|
||||
return;
|
||||
}
|
||||
di->prot = prot;
|
||||
di->sd_resp = buf;
|
||||
di->sd_resp_pos = 0;
|
||||
tx_buf = gas_anqp_build_initial_resp_buf(
|
||||
@ -819,7 +827,8 @@ static void gas_serv_req_local_processing(struct hostapd_data *hapd,
|
||||
}
|
||||
if (!tx_buf)
|
||||
return;
|
||||
|
||||
if (prot)
|
||||
convert_to_protected_dual(tx_buf);
|
||||
hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
|
||||
wpabuf_head(tx_buf), wpabuf_len(tx_buf));
|
||||
wpabuf_free(tx_buf);
|
||||
@ -828,7 +837,7 @@ static void gas_serv_req_local_processing(struct hostapd_data *hapd,
|
||||
|
||||
static void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd,
|
||||
const u8 *sa,
|
||||
const u8 *data, size_t len)
|
||||
const u8 *data, size_t len, int prot)
|
||||
{
|
||||
const u8 *pos = data;
|
||||
const u8 *end = data + len;
|
||||
@ -878,6 +887,8 @@ static void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd,
|
||||
return;
|
||||
wpabuf_put_data(buf, adv_proto, 2 + slen);
|
||||
wpabuf_put_le16(buf, 0); /* Query Response Length */
|
||||
if (prot)
|
||||
convert_to_protected_dual(buf);
|
||||
hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
|
||||
wpabuf_head(buf), wpabuf_len(buf));
|
||||
wpabuf_free(buf);
|
||||
@ -929,7 +940,7 @@ static void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd,
|
||||
pos += elen;
|
||||
}
|
||||
|
||||
gas_serv_req_local_processing(hapd, sa, dialog_token, &qi);
|
||||
gas_serv_req_local_processing(hapd, sa, dialog_token, &qi, prot);
|
||||
}
|
||||
|
||||
|
||||
@ -975,6 +986,8 @@ void gas_serv_tx_gas_response(struct hostapd_data *hapd, const u8 *dst,
|
||||
if (tx_buf) {
|
||||
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
|
||||
"GAS: Tx GAS Initial Resp (comeback = 10TU)");
|
||||
if (dialog->prot)
|
||||
convert_to_protected_dual(tx_buf);
|
||||
hostapd_drv_send_action(hapd, hapd->iface->freq, 0,
|
||||
dst,
|
||||
wpabuf_head(tx_buf),
|
||||
@ -1012,6 +1025,8 @@ void gas_serv_tx_gas_response(struct hostapd_data *hapd, const u8 *dst,
|
||||
dialog->sd_frag_id, (int) frag_len);
|
||||
dialog->sd_frag_id++;
|
||||
|
||||
if (dialog->prot)
|
||||
convert_to_protected_dual(tx_buf);
|
||||
hostapd_drv_send_action(hapd, hapd->iface->freq, 0, dst,
|
||||
wpabuf_head(tx_buf), wpabuf_len(tx_buf));
|
||||
wpabuf_free(tx_buf);
|
||||
@ -1022,7 +1037,7 @@ tx_gas_response_done:
|
||||
|
||||
static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd,
|
||||
const u8 *sa,
|
||||
const u8 *data, size_t len)
|
||||
const u8 *data, size_t len, int prot)
|
||||
{
|
||||
struct gas_dialog_info *dialog;
|
||||
struct wpabuf *buf, *tx_buf;
|
||||
@ -1120,6 +1135,8 @@ static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd,
|
||||
}
|
||||
|
||||
send_resp:
|
||||
if (prot)
|
||||
convert_to_protected_dual(tx_buf);
|
||||
hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
|
||||
wpabuf_head(tx_buf), wpabuf_len(tx_buf));
|
||||
wpabuf_free(tx_buf);
|
||||
@ -1137,22 +1154,30 @@ static void gas_serv_rx_public_action(void *ctx, const u8 *buf, size_t len,
|
||||
const struct ieee80211_mgmt *mgmt;
|
||||
size_t hdr_len;
|
||||
const u8 *sa, *data;
|
||||
int prot;
|
||||
|
||||
mgmt = (const struct ieee80211_mgmt *) buf;
|
||||
hdr_len = (const u8 *) &mgmt->u.action.u.vs_public_action.action - buf;
|
||||
if (hdr_len > len)
|
||||
return;
|
||||
if (mgmt->u.action.category != WLAN_ACTION_PUBLIC)
|
||||
if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
|
||||
mgmt->u.action.category != WLAN_ACTION_PROTECTED_DUAL)
|
||||
return;
|
||||
/*
|
||||
* Note: Public Action and Protected Dual of Public Action frames share
|
||||
* the same payload structure, so it is fine to use definitions of
|
||||
* Public Action frames to process both.
|
||||
*/
|
||||
prot = mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL;
|
||||
sa = mgmt->sa;
|
||||
len -= hdr_len;
|
||||
data = &mgmt->u.action.u.public_action.action;
|
||||
switch (data[0]) {
|
||||
case WLAN_PA_GAS_INITIAL_REQ:
|
||||
gas_serv_rx_gas_initial_req(hapd, sa, data + 1, len - 1);
|
||||
gas_serv_rx_gas_initial_req(hapd, sa, data + 1, len - 1, prot);
|
||||
break;
|
||||
case WLAN_PA_GAS_COMEBACK_REQ:
|
||||
gas_serv_rx_gas_comeback_req(hapd, sa, data + 1, len - 1);
|
||||
gas_serv_rx_gas_comeback_req(hapd, sa, data + 1, len - 1, prot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ struct gas_dialog_info {
|
||||
size_t sd_resp_pos; /* Offset in sd_resp */
|
||||
u8 sd_frag_id;
|
||||
u16 comeback_delay;
|
||||
int prot; /* whether Protected Dual of Public Action frame is used */
|
||||
|
||||
unsigned int requested;
|
||||
unsigned int received;
|
||||
|
@ -1619,6 +1619,7 @@ static int handle_action(struct hostapd_data *hapd,
|
||||
return 1;
|
||||
#endif /* CONFIG_WNM */
|
||||
case WLAN_ACTION_PUBLIC:
|
||||
case WLAN_ACTION_PROTECTED_DUAL:
|
||||
if (hapd->public_action_cb) {
|
||||
hapd->public_action_cb(hapd->public_action_cb_ctx,
|
||||
(u8 *) mgmt, len,
|
||||
|
@ -360,6 +360,8 @@ static void ap_public_action_rx(void *ctx, const u8 *buf, size_t len, int freq)
|
||||
hdr_len = (const u8 *) &mgmt->u.action.u.vs_public_action.action - buf;
|
||||
if (hdr_len > len)
|
||||
return;
|
||||
if (mgmt->u.action.category != WLAN_ACTION_PUBLIC)
|
||||
return;
|
||||
wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
|
||||
mgmt->u.action.category,
|
||||
&mgmt->u.action.u.vs_public_action.action,
|
||||
|
Loading…
Reference in New Issue
Block a user