WPS: Allow pending WPS operation to be cancelled
A new ctrl_interface command, WPS_CANCEL, can now be used to cancel a pending or ongoing WPS operation. For now, this is only available with wpa_supplicant (either in station or AP mode). Similar functionality should be added for hostapd, too.
This commit is contained in:
parent
fbe7027239
commit
2f9929ffcc
8 changed files with 146 additions and 20 deletions
|
@ -721,6 +721,7 @@ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr,
|
|||
const u8 *uuid, const u8 *pin, size_t pin_len,
|
||||
int timeout);
|
||||
int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid);
|
||||
int wps_registrar_wps_cancel(struct wps_registrar *reg);
|
||||
int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid);
|
||||
int wps_registrar_button_pushed(struct wps_registrar *reg);
|
||||
void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr,
|
||||
|
|
|
@ -662,6 +662,22 @@ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr,
|
|||
}
|
||||
|
||||
|
||||
static void wps_registrar_remove_pin(struct wps_registrar *reg,
|
||||
struct wps_uuid_pin *pin)
|
||||
{
|
||||
u8 *addr;
|
||||
u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
if (is_zero_ether_addr(pin->enrollee_addr))
|
||||
addr = bcast;
|
||||
else
|
||||
addr = pin->enrollee_addr;
|
||||
wps_registrar_remove_authorized_mac(reg, addr);
|
||||
wps_remove_pin(pin);
|
||||
wps_registrar_selected_registrar_changed(reg);
|
||||
}
|
||||
|
||||
|
||||
static void wps_registrar_expire_pins(struct wps_registrar *reg)
|
||||
{
|
||||
struct wps_uuid_pin *pin, *prev;
|
||||
|
@ -672,23 +688,37 @@ static void wps_registrar_expire_pins(struct wps_registrar *reg)
|
|||
{
|
||||
if ((pin->flags & PIN_EXPIRES) &&
|
||||
os_time_before(&pin->expiration, &now)) {
|
||||
u8 *addr;
|
||||
u8 bcast[ETH_ALEN] =
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
wpa_hexdump(MSG_DEBUG, "WPS: Expired PIN for UUID",
|
||||
pin->uuid, WPS_UUID_LEN);
|
||||
if (is_zero_ether_addr(pin->enrollee_addr))
|
||||
addr = bcast;
|
||||
else
|
||||
addr = pin->enrollee_addr;
|
||||
wps_registrar_remove_authorized_mac(reg, addr);
|
||||
wps_remove_pin(pin);
|
||||
wps_registrar_selected_registrar_changed(reg);
|
||||
wps_registrar_remove_pin(reg, pin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wps_registrar_invalidate_wildcard_pin - Invalidate a wildcard PIN
|
||||
* @reg: Registrar data from wps_registrar_init()
|
||||
* Returns: 0 on success, -1 if not wildcard PIN is enabled
|
||||
*/
|
||||
static int wps_registrar_invalidate_wildcard_pin(struct wps_registrar *reg)
|
||||
{
|
||||
struct wps_uuid_pin *pin, *prev;
|
||||
|
||||
dl_list_for_each_safe(pin, prev, ®->pins, struct wps_uuid_pin, list)
|
||||
{
|
||||
if (pin->wildcard_uuid) {
|
||||
wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID",
|
||||
pin->uuid, WPS_UUID_LEN);
|
||||
wps_registrar_remove_pin(reg, pin);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wps_registrar_invalidate_pin - Invalidate a PIN for a specific UUID-E
|
||||
* @reg: Registrar data from wps_registrar_init()
|
||||
|
@ -702,18 +732,9 @@ int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid)
|
|||
dl_list_for_each_safe(pin, prev, ®->pins, struct wps_uuid_pin, list)
|
||||
{
|
||||
if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) {
|
||||
u8 *addr;
|
||||
u8 bcast[ETH_ALEN] =
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID",
|
||||
pin->uuid, WPS_UUID_LEN);
|
||||
if (is_zero_ether_addr(pin->enrollee_addr))
|
||||
addr = bcast;
|
||||
else
|
||||
addr = pin->enrollee_addr;
|
||||
wps_registrar_remove_authorized_mac(reg, addr);
|
||||
wps_remove_pin(pin);
|
||||
wps_registrar_selected_registrar_changed(reg);
|
||||
wps_registrar_remove_pin(reg, pin);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -865,6 +886,23 @@ static void wps_registrar_pin_completed(struct wps_registrar *reg)
|
|||
}
|
||||
|
||||
|
||||
int wps_registrar_wps_cancel(struct wps_registrar *reg)
|
||||
{
|
||||
if (reg->pbc) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: PBC is set - cancelling it");
|
||||
wps_registrar_pbc_timeout(reg, NULL);
|
||||
return 1;
|
||||
} else if (reg->selected_registrar) {
|
||||
/* PIN Method */
|
||||
wpa_printf(MSG_DEBUG, "WPS: PIN is set - cancelling it");
|
||||
wps_registrar_pin_completed(reg);
|
||||
wps_registrar_invalidate_wildcard_pin(reg);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wps_registrar_probe_req_rx - Notify Registrar of Probe Request
|
||||
* @reg: Registrar data from wps_registrar_init()
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "driver_i.h"
|
||||
#include "p2p_supplicant.h"
|
||||
#include "ap.h"
|
||||
#include "ap/sta_info.h"
|
||||
|
||||
|
||||
static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
|
||||
|
@ -477,6 +478,51 @@ int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid)
|
|||
}
|
||||
|
||||
|
||||
static int wpa_supplicant_ap_wps_sta_cancel(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, void *ctx)
|
||||
{
|
||||
if (sta && (sta->flags & WLAN_STA_WPS)) {
|
||||
ap_sta_deauthenticate(hapd, sta,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
wpa_printf(MSG_DEBUG, "WPS: %s: Deauth sta=" MACSTR,
|
||||
__func__, MAC2STR(sta->addr));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wpa_supplicant_ap_wps_cancel(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
struct wps_registrar *reg;
|
||||
int reg_sel = 0, wps_sta = 0;
|
||||
|
||||
if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]->wps)
|
||||
return -1;
|
||||
|
||||
reg = wpa_s->ap_iface->bss[0]->wps->registrar;
|
||||
reg_sel = wps_registrar_wps_cancel(reg);
|
||||
wps_sta = ap_for_each_sta(wpa_s->ap_iface->bss[0],
|
||||
wpa_supplicant_ap_wps_sta_cancel, NULL);
|
||||
|
||||
if (!reg_sel && !wps_sta) {
|
||||
wpa_printf(MSG_DEBUG, "No WPS operation in progress at this "
|
||||
"time");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are 2 cases to return wps cancel as success:
|
||||
* 1. When wps cancel was initiated but no connection has been
|
||||
* established with client yet.
|
||||
* 2. Client is in the middle of exchanging WPS messages.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||
const char *pin, char *buf, size_t buflen)
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@ void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
|
|||
int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid);
|
||||
int wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||
const char *pin, char *buf, size_t buflen);
|
||||
int wpa_supplicant_ap_wps_cancel(struct wpa_supplicant *wpa_s);
|
||||
int ap_ctrl_iface_sta_first(struct wpa_supplicant *wpa_s,
|
||||
char *buf, size_t buflen);
|
||||
int ap_ctrl_iface_sta(struct wpa_supplicant *wpa_s, const char *txtaddr,
|
||||
|
|
|
@ -2687,6 +2687,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
|||
reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
|
||||
reply,
|
||||
reply_size);
|
||||
} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
|
||||
if (wpas_wps_cancel(wpa_s))
|
||||
reply_len = -1;
|
||||
#ifdef CONFIG_WPS_OOB
|
||||
} else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
|
||||
if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
|
||||
|
|
|
@ -615,6 +615,13 @@ static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
|||
}
|
||||
|
||||
|
||||
static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
return wpa_ctrl_command(ctrl, "WPS_CANCEL");
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS_OOB
|
||||
static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||
{
|
||||
|
@ -2244,6 +2251,8 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
|
|||
cli_cmd_flag_sensitive,
|
||||
"<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
|
||||
"hardcoded)" },
|
||||
{ "wps_cancel", wpa_cli_cmd_wps_cancel, cli_cmd_flag_none,
|
||||
"Cancels the pending WPS operation" },
|
||||
#ifdef CONFIG_WPS_OOB
|
||||
{ "wps_oob", wpa_cli_cmd_wps_oob,
|
||||
cli_cmd_flag_sensitive,
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "blacklist.h"
|
||||
#include "bss.h"
|
||||
#include "scan.h"
|
||||
#include "ap.h"
|
||||
#include "p2p/p2p.h"
|
||||
#include "p2p_supplicant.h"
|
||||
#include "wps_supplicant.h"
|
||||
|
@ -757,6 +758,32 @@ int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
|||
}
|
||||
|
||||
|
||||
/* Cancel the wps pbc/pin requests */
|
||||
int wpas_wps_cancel(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
#ifdef CONFIG_AP
|
||||
if (wpa_s->ap_iface) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: Cancelling in AP mode");
|
||||
return wpa_supplicant_ap_wps_cancel(wpa_s);
|
||||
}
|
||||
#endif /* CONFIG_AP */
|
||||
|
||||
if (wpa_s->wpa_state == WPA_SCANNING) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: Cancel operation - cancel scan");
|
||||
wpa_supplicant_cancel_scan(wpa_s);
|
||||
wpas_clear_wps(wpa_s);
|
||||
} else if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: Cancel operation - "
|
||||
"deauthenticate");
|
||||
wpa_supplicant_deauthenticate(wpa_s,
|
||||
WLAN_REASON_DEAUTH_LEAVING);
|
||||
wpas_clear_wps(wpa_s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS_OOB
|
||||
int wpas_wps_start_oob(struct wpa_supplicant *wpa_s, char *device_type,
|
||||
char *path, char *method, char *name)
|
||||
|
|
|
@ -39,6 +39,7 @@ int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
|||
int p2p_group);
|
||||
int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||
const char *pin, int p2p_group, u16 dev_pw_id);
|
||||
int wpas_wps_cancel(struct wpa_supplicant *wpa_s);
|
||||
int wpas_wps_start_oob(struct wpa_supplicant *wpa_s, char *device_type,
|
||||
char *path, char *method, char *name);
|
||||
int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||
|
|
Loading…
Reference in a new issue