DPP2: Accept Config Result before GAS response TX status

The TX event for the next frame in the sequence might be received before
the TX status for the final GAS response frame is processed. This used
to result in the Config Result getting discarded and the negotiation not
completing successfully on the Configurator side.

Accept the Config Result message as an indication of the final GAS
response frame having went through fine even if the TX status has not
yet been processed to avoid this issue from a potential race condition
on kernel events.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2021-02-21 16:44:33 +02:00
parent 6518c72b02
commit 976c3c161f
4 changed files with 36 additions and 4 deletions

View file

@ -348,6 +348,7 @@ struct dpp_authentication {
struct wpabuf *cacert;
struct wpabuf *certbag;
void *cert_resp_ctx;
void *gas_server_ctx;
#ifdef CONFIG_TESTING_OPTIONS
char *config_obj_override;
char *discovery_override;

View file

@ -489,6 +489,21 @@ int gas_server_set_resp(struct gas_server *gas, void *resp_ctx,
}
bool gas_server_response_sent(struct gas_server *gas, void *resp_ctx)
{
struct gas_server_response *tmp;
dl_list_for_each(tmp, &gas->responses, struct gas_server_response,
list) {
if (tmp == resp_ctx)
return tmp->resp &&
tmp->offset == wpabuf_len(tmp->resp);
}
return false;
}
struct gas_server * gas_server_init(void *ctx,
void (*tx)(void *ctx, int freq,
const u8 *da,

View file

@ -36,6 +36,7 @@ void gas_server_tx_status(struct gas_server *gas, const u8 *dst, const u8 *data,
size_t data_len, int ack);
int gas_server_set_resp(struct gas_server *gas, void *resp_ctx,
struct wpabuf *resp);
bool gas_server_response_sent(struct gas_server *gas, void *resp_ctx);
#else /* CONFIG_GAS_SERVER */

View file

@ -1918,9 +1918,22 @@ static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
MAC2STR(src));
if (!auth || !auth->waiting_conf_result) {
wpa_printf(MSG_DEBUG,
"DPP: No DPP Configuration waiting for result - drop");
return;
if (auth &&
os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) == 0 &&
gas_server_response_sent(wpa_s->gas_server,
auth->gas_server_ctx)) {
/* This could happen if the TX status event gets delayed
* long enough for the Enrollee to have time to send
* the next frame before the TX status gets processed
* locally. */
wpa_printf(MSG_DEBUG,
"DPP: GAS response was sent but TX status not yet received - assume it was ACKed since the Enrollee sent the next frame in the sequence");
auth->waiting_conf_result = 1;
} else {
wpa_printf(MSG_DEBUG,
"DPP: No DPP Configuration waiting for result - drop");
return;
}
}
if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
@ -2969,6 +2982,7 @@ wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
if (!resp)
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
auth->conf_resp = resp;
auth->gas_server_ctx = resp_ctx;
return resp;
}
@ -3006,7 +3020,8 @@ wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
#ifdef CONFIG_DPP2
if (ok && auth->peer_version >= 2 &&
auth->conf_resp_status == DPP_STATUS_OK) {
auth->conf_resp_status == DPP_STATUS_OK &&
!auth->waiting_conf_result) {
wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
auth->waiting_conf_result = 1;
auth->conf_resp = NULL;