aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hostapd/ctrl_iface.c2
-rw-r--r--src/ap/drv_callbacks.c2
-rw-r--r--src/ap/wps_hostapd.c9
-rw-r--r--src/ap/wps_hostapd.h6
-rw-r--r--src/eap_server/eap_server_wsc.c4
-rw-r--r--src/wps/wps.c2
-rw-r--r--src/wps/wps.h13
-rw-r--r--src/wps/wps_er.c2
-rw-r--r--src/wps/wps_i.h2
-rw-r--r--src/wps/wps_registrar.c39
-rw-r--r--wpa_supplicant/ap.c6
-rw-r--r--wpa_supplicant/ap.h3
-rw-r--r--wpa_supplicant/ctrl_iface.c17
-rw-r--r--wpa_supplicant/p2p_supplicant.c3
14 files changed, 92 insertions, 18 deletions
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index d3ab624..195b8a7 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -865,7 +865,7 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
reply_len = hostapd_ctrl_iface_wps_check_pin(
hapd, buf + 14, reply, reply_size);
} else if (os_strcmp(buf, "WPS_PBC") == 0) {
- if (hostapd_wps_button_pushed(hapd))
+ if (hostapd_wps_button_pushed(hapd, NULL))
reply_len = -1;
#ifdef CONFIG_WPS_OOB
} else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index a49248f..c1fdba6 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -463,7 +463,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
#endif /* CONFIG_IEEE80211R */
case EVENT_WPS_BUTTON_PUSHED:
- hostapd_wps_button_pushed(hapd);
+ hostapd_wps_button_pushed(hapd, NULL);
break;
#ifdef NEED_AP_MLME
case EVENT_TX_STATUS:
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index cfff55c..d5042c0 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -965,15 +965,18 @@ int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr,
static int wps_button_pushed(struct hostapd_data *hapd, void *ctx)
{
+ const u8 *p2p_dev_addr = ctx;
if (hapd->wps == NULL)
return 0;
- return wps_registrar_button_pushed(hapd->wps->registrar);
+ return wps_registrar_button_pushed(hapd->wps->registrar, p2p_dev_addr);
}
-int hostapd_wps_button_pushed(struct hostapd_data *hapd)
+int hostapd_wps_button_pushed(struct hostapd_data *hapd,
+ const u8 *p2p_dev_addr)
{
- return hostapd_wps_for_each(hapd, wps_button_pushed, NULL);
+ return hostapd_wps_for_each(hapd, wps_button_pushed,
+ (void *) p2p_dev_addr);
}
diff --git a/src/ap/wps_hostapd.h b/src/ap/wps_hostapd.h
index 36401be..338a220 100644
--- a/src/ap/wps_hostapd.h
+++ b/src/ap/wps_hostapd.h
@@ -23,7 +23,8 @@ void hostapd_deinit_wps(struct hostapd_data *hapd);
void hostapd_update_wps(struct hostapd_data *hapd);
int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr,
const char *uuid, const char *pin, int timeout);
-int hostapd_wps_button_pushed(struct hostapd_data *hapd);
+int hostapd_wps_button_pushed(struct hostapd_data *hapd,
+ const u8 *p2p_dev_addr);
int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
char *path, char *method, char *name);
int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr,
@@ -60,7 +61,8 @@ static inline int hostapd_wps_get_mib_sta(struct hostapd_data *hapd,
return 0;
}
-static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd)
+static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd,
+ const u8 *p2p_dev_addr)
{
return 0;
}
diff --git a/src/eap_server/eap_server_wsc.c b/src/eap_server/eap_server_wsc.c
index 83e55d9..e944a4d 100644
--- a/src/eap_server/eap_server_wsc.c
+++ b/src/eap_server/eap_server_wsc.c
@@ -18,6 +18,7 @@
#include "eloop.h"
#include "eap_i.h"
#include "eap_common/eap_wsc_common.h"
+#include "p2p/p2p.h"
#include "wps/wps.h"
@@ -135,11 +136,14 @@ static void * eap_wsc_init(struct eap_sm *sm)
}
cfg.assoc_wps_ie = sm->assoc_wps_ie;
cfg.peer_addr = sm->peer_addr;
+#ifdef CONFIG_P2P
if (sm->assoc_p2p_ie) {
wpa_printf(MSG_DEBUG, "EAP-WSC: Prefer PSK format for P2P "
"client");
cfg.use_psk_key = 1;
+ cfg.p2p_dev_addr = p2p_get_go_dev_addr(sm->assoc_p2p_ie);
}
+#endif /* CONFIG_P2P */
data->wps = wps_init(&cfg);
if (data->wps == NULL) {
os_free(data);
diff --git a/src/wps/wps.c b/src/wps/wps.c
index 73dd58c..a9d41d0 100644
--- a/src/wps/wps.c
+++ b/src/wps/wps.c
@@ -109,6 +109,8 @@ struct wps_data * wps_init(const struct wps_config *cfg)
if (cfg->peer_addr)
os_memcpy(data->peer_dev.mac_addr, cfg->peer_addr, ETH_ALEN);
+ if (cfg->p2p_dev_addr)
+ os_memcpy(data->p2p_dev_addr, cfg->p2p_dev_addr, ETH_ALEN);
data->use_psk_key = cfg->use_psk_key;
diff --git a/src/wps/wps.h b/src/wps/wps.h
index 771551a..47b3e76 100644
--- a/src/wps/wps.h
+++ b/src/wps/wps.h
@@ -164,6 +164,16 @@ struct wps_config {
* dev_pw_id - Device Password ID for Enrollee when PIN is used
*/
u16 dev_pw_id;
+
+ /**
+ * p2p_dev_addr - P2P Device Address from (Re)Association Request
+ *
+ * On AP/GO, this is set to the P2P Device Address of the associating
+ * P2P client if a P2P IE is included in the (Re)Association Request
+ * frame and the P2P Device Address is included. Otherwise, this is set
+ * to %NULL to indicate the station does not have a P2P Device Address.
+ */
+ const u8 *p2p_dev_addr;
};
struct wps_data * wps_init(const struct wps_config *cfg);
@@ -747,7 +757,8 @@ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr,
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);
+int wps_registrar_button_pushed(struct wps_registrar *reg,
+ const u8 *p2p_dev_addr);
void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr,
const struct wpabuf *wps_data,
int p2p_wildcard);
diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c
index d3aee2d..a461836 100644
--- a/src/wps/wps_er.c
+++ b/src/wps/wps_er.c
@@ -1550,7 +1550,7 @@ int wps_er_pbc(struct wps_er *er, const u8 *uuid)
}
er->set_sel_reg_uuid_filter = uuid;
- res = wps_registrar_button_pushed(er->wps->registrar);
+ res = wps_registrar_button_pushed(er->wps->registrar, NULL);
er->set_sel_reg_uuid_filter = NULL;
if (res)
return -1;
diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h
index 316e1f6..a9f8949 100644
--- a/src/wps/wps_i.h
+++ b/src/wps/wps_i.h
@@ -117,6 +117,8 @@ struct wps_data {
struct wps_credential *use_cred;
int use_psk_key;
+ u8 p2p_dev_addr[ETH_ALEN]; /* P2P Device Address of the client or
+ * 00:00:00:00:00:00 if not a P2p client */
};
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index ec429f8..a01066c 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -135,6 +135,8 @@ struct wps_registrar {
u8 authorized_macs[WPS_MAX_AUTHORIZED_MACS][ETH_ALEN];
u8 authorized_macs_union[WPS_MAX_AUTHORIZED_MACS][ETH_ALEN];
+
+ u8 p2p_dev_addr[ETH_ALEN];
};
@@ -842,6 +844,7 @@ static void wps_registrar_stop_pbc(struct wps_registrar *reg)
{
reg->selected_registrar = 0;
reg->pbc = 0;
+ os_memset(reg->p2p_dev_addr, 0, ETH_ALEN);
wps_registrar_remove_authorized_mac(reg,
(u8 *) "\xff\xff\xff\xff\xff\xff");
wps_registrar_selected_registrar_changed(reg);
@@ -861,13 +864,16 @@ static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx)
/**
* wps_registrar_button_pushed - Notify Registrar that AP button was pushed
* @reg: Registrar data from wps_registrar_init()
+ * @p2p_dev_addr: Limit allowed PBC devices to the specified P2P device, %NULL
+ * indicates no such filtering
* Returns: 0 on success, -1 on failure
*
* This function is called on an AP when a push button is pushed to activate
* PBC mode. The PBC mode will be stopped after walk time (2 minutes) timeout
* or when a PBC registration is completed.
*/
-int wps_registrar_button_pushed(struct wps_registrar *reg)
+int wps_registrar_button_pushed(struct wps_registrar *reg,
+ const u8 *p2p_dev_addr)
{
if (wps_registrar_pbc_overlap(reg, NULL, NULL)) {
wpa_printf(MSG_DEBUG, "WPS: PBC overlap - do not start PBC "
@@ -879,6 +885,10 @@ int wps_registrar_button_pushed(struct wps_registrar *reg)
reg->force_pbc_overlap = 0;
reg->selected_registrar = 1;
reg->pbc = 1;
+ if (p2p_dev_addr)
+ os_memcpy(reg->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
+ else
+ os_memset(reg->p2p_dev_addr, 0, ETH_ALEN);
wps_registrar_add_authorized_mac(reg,
(u8 *) "\xff\xff\xff\xff\xff\xff");
wps_registrar_selected_registrar_changed(reg);
@@ -2226,6 +2236,27 @@ static int wps_process_config_error(struct wps_data *wps, const u8 *err)
}
+static int wps_registrar_p2p_dev_addr_match(struct wps_data *wps)
+{
+#ifdef CONFIG_P2P
+ struct wps_registrar *reg = wps->wps->registrar;
+
+ if (is_zero_ether_addr(reg->p2p_dev_addr))
+ return 1; /* no filtering in use */
+
+ if (os_memcmp(reg->p2p_dev_addr, wps->p2p_dev_addr, ETH_ALEN) != 0) {
+ wpa_printf(MSG_DEBUG, "WPS: No match on P2P Device Address "
+ "filtering for PBC: expected " MACSTR " was "
+ MACSTR " - indicate PBC session overlap",
+ MAC2STR(reg->p2p_dev_addr),
+ MAC2STR(wps->p2p_dev_addr));
+ return 0;
+ }
+#endif /* CONFIG_P2P */
+ return 1;
+}
+
+
static enum wps_process_res wps_process_m1(struct wps_data *wps,
struct wps_parse_attr *attr)
{
@@ -2280,12 +2311,16 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps,
if (wps->dev_pw_id == DEV_PW_PUSHBUTTON) {
if (wps->wps->registrar->force_pbc_overlap ||
wps_registrar_pbc_overlap(wps->wps->registrar,
- wps->mac_addr_e, wps->uuid_e)) {
+ wps->mac_addr_e, wps->uuid_e) ||
+ !wps_registrar_p2p_dev_addr_match(wps)) {
wpa_printf(MSG_DEBUG, "WPS: PBC overlap - deny PBC "
"negotiation");
wps->state = SEND_M2D;
wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED;
wps_pbc_overlap_event(wps->wps);
+ wps_fail_event(wps->wps, WPS_M1,
+ WPS_CFG_MULTIPLE_PBC_DETECTED,
+ WPS_EI_NO_ERROR);
wps->wps->registrar->force_pbc_overlap = 1;
return WPS_CONTINUE;
}
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 26ccdea..2597816 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -517,11 +517,13 @@ void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_WPS
-int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid)
+int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const u8 *p2p_dev_addr)
{
if (!wpa_s->ap_iface)
return -1;
- return hostapd_wps_button_pushed(wpa_s->ap_iface->bss[0]);
+ return hostapd_wps_button_pushed(wpa_s->ap_iface->bss[0],
+ p2p_dev_addr);
}
diff --git a/wpa_supplicant/ap.h b/wpa_supplicant/ap.h
index d3bab24..b913be3 100644
--- a/wpa_supplicant/ap.h
+++ b/wpa_supplicant/ap.h
@@ -21,7 +21,8 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
void wpa_supplicant_ap_deinit(struct wpa_supplicant *wpa_s);
void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
const u8 *src_addr, const u8 *buf, size_t len);
-int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid);
+int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const u8 *p2p_dev_addr);
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);
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 7731895..31ec5d6 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -213,10 +213,21 @@ static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
char *cmd)
{
u8 bssid[ETH_ALEN], *_bssid = bssid;
+ u8 p2p_dev_addr[ETH_ALEN], *_p2p_dev_addr = NULL;
- if (cmd == NULL || os_strcmp(cmd, "any") == 0)
+ if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
_bssid = NULL;
- else if (hwaddr_aton(cmd, bssid)) {
+#ifdef CONFIG_P2P
+ } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
+ if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
+ "P2P Device Address '%s'",
+ cmd + 13);
+ return -1;
+ }
+ _p2p_dev_addr = p2p_dev_addr;
+#endif /* CONFIG_P2P */
+ } else if (hwaddr_aton(cmd, bssid)) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
cmd);
return -1;
@@ -224,7 +235,7 @@ static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_AP
if (wpa_s->ap_iface)
- return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid);
+ return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
#endif /* CONFIG_AP */
return wpas_wps_start_pbc(wpa_s, _bssid, 0);
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index dfc50c5..85c3fbe 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -857,7 +857,8 @@ static void p2p_go_configured(void *ctx, void *data)
return;
}
if (params->wps_method == WPS_PBC)
- wpa_supplicant_ap_wps_pbc(wpa_s, params->peer_interface_addr);
+ wpa_supplicant_ap_wps_pbc(wpa_s, params->peer_interface_addr,
+ NULL);
else if (wpa_s->p2p_pin[0])
wpa_supplicant_ap_wps_pin(wpa_s, params->peer_interface_addr,
wpa_s->p2p_pin, NULL, 0);