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:
Ardong Chen 2010-09-06 20:51:06 +03:00 committed by Jouni Malinen
parent fbe7027239
commit 2f9929ffcc
8 changed files with 146 additions and 20 deletions

View file

@ -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,

View file

@ -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, &reg->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, &reg->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()

View file

@ -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)
{

View file

@ -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,

View file

@ -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))

View file

@ -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,

View file

@ -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)

View file

@ -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,