WPS: Fix multi-interface WPS operations in hostapd

Couple of the for-each-interface loops used incorrect return value when
skipping over non-WPS interfaces. This could result in skipping some WPS
interfaces in the loop and returning error. Setting AP PIN did not check
for WPS being enabled at all and trigger a NULL pointer dereference if
non-WPS interface was enabled.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2015-08-16 22:38:31 +03:00
parent a8fd08f7fc
commit e1938ba934
1 changed files with 45 additions and 11 deletions

View File

@ -1304,30 +1304,53 @@ int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr,
}
struct wps_button_pushed_ctx {
const u8 *p2p_dev_addr;
unsigned int count;
};
static int wps_button_pushed(struct hostapd_data *hapd, void *ctx)
{
const u8 *p2p_dev_addr = ctx;
if (hapd->wps == NULL)
return -1;
return wps_registrar_button_pushed(hapd->wps->registrar, p2p_dev_addr);
struct wps_button_pushed_ctx *data = ctx;
if (hapd->wps) {
data->count++;
return wps_registrar_button_pushed(hapd->wps->registrar,
data->p2p_dev_addr);
}
return 0;
}
int hostapd_wps_button_pushed(struct hostapd_data *hapd,
const u8 *p2p_dev_addr)
{
return hostapd_wps_for_each(hapd, wps_button_pushed,
(void *) p2p_dev_addr);
struct wps_button_pushed_ctx ctx;
int ret;
os_memset(&ctx, 0, sizeof(ctx));
ctx.p2p_dev_addr = p2p_dev_addr;
ret = hostapd_wps_for_each(hapd, wps_button_pushed, &ctx);
if (ret == 0 && !ctx.count)
ret = -1;
return ret;
}
struct wps_cancel_ctx {
unsigned int count;
};
static int wps_cancel(struct hostapd_data *hapd, void *ctx)
{
if (hapd->wps == NULL)
return -1;
struct wps_cancel_ctx *data = ctx;
wps_registrar_wps_cancel(hapd->wps->registrar);
ap_for_each_sta(hapd, ap_sta_wps_cancel, NULL);
if (hapd->wps) {
data->count++;
wps_registrar_wps_cancel(hapd->wps->registrar);
ap_for_each_sta(hapd, ap_sta_wps_cancel, NULL);
}
return 0;
}
@ -1335,7 +1358,14 @@ static int wps_cancel(struct hostapd_data *hapd, void *ctx)
int hostapd_wps_cancel(struct hostapd_data *hapd)
{
return hostapd_wps_for_each(hapd, wps_cancel, NULL);
struct wps_cancel_ctx ctx;
int ret;
os_memset(&ctx, 0, sizeof(ctx));
ret = hostapd_wps_for_each(hapd, wps_cancel, &ctx);
if (ret == 0 && !ctx.count)
ret = -1;
return ret;
}
@ -1565,6 +1595,10 @@ struct wps_ap_pin_data {
static int wps_ap_pin_set(struct hostapd_data *hapd, void *ctx)
{
struct wps_ap_pin_data *data = ctx;
if (!hapd->wps)
return 0;
os_free(hapd->conf->ap_pin);
hapd->conf->ap_pin = os_strdup(data->pin_txt);
#ifdef CONFIG_WPS_UPNP