WPS: Add a workaround for Windows 7 capability discovery for PBC

Windows 7 uses incorrect way of figuring out AP's WPS capabilities by
acting as a Registrar and using M1 from the AP. The config methods
attribute in that message is supposed to indicate only the configuration
method supported by the AP in Enrollee role, i.e., to add an external
Registrar. For that case, PBC shall not be used and as such, the
PushButton config method is removed from M1 by default. If pbc_in_m1=1
is included in the configuration file, the PushButton config method is
left in M1 (if included in config_methods parameter) to allow Windows 7
to use PBC instead of PIN (e.g., from a label in the AP).
This commit is contained in:
Jouni Malinen 2011-05-17 19:53:02 +03:00 committed by Jouni Malinen
parent bcb90f750d
commit fa5165586f
14 changed files with 43 additions and 1 deletions

View file

@ -2021,6 +2021,8 @@ struct hostapd_config * hostapd_config_read(const char *fname)
} else if (os_strcmp(buf, "upc") == 0) {
os_free(bss->upc);
bss->upc = os_strdup(pos);
} else if (os_strcmp(buf, "pbc_in_m1") == 0) {
bss->pbc_in_m1 = atoi(pos);
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P_MANAGER
} else if (os_strcmp(buf, "manage_p2p") == 0) {

View file

@ -921,6 +921,18 @@ own_ip_addr=127.0.0.1
# virtual_push_button physical_push_button
#config_methods=label virtual_display virtual_push_button keypad
# WPS capability discovery workaround for PBC with Windows 7
# Windows 7 uses incorrect way of figuring out AP's WPS capabilities by acting
# as a Registrar and using M1 from the AP. The config methods attribute in that
# message is supposed to indicate only the configuration method supported by
# the AP in Enrollee role, i.e., to add an external Registrar. For that case,
# PBC shall not be used and as such, the PushButton config method is removed
# from M1 by default. If pbc_in_m1=1 is included in the configuration file,
# the PushButton config method is left in M1 (if included in config_methods
# parameter) to allow Windows 7 to use PBC instead of PIN (e.g., from a label
# in the AP).
#pbc_in_m1=1
# Static access point PIN for initial configuration and adding Registrars
# If not set, hostapd will not allow external WPS Registrars to control the
# access point. The AP PIN can also be set at runtime with hostapd_cli

View file

@ -318,6 +318,7 @@ struct hostapd_bss_config {
char *upc;
struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
#endif /* CONFIG_WPS */
int pbc_in_m1;
#define P2P_ENABLED BIT(0)
#define P2P_GROUP_OWNER BIT(1)

View file

@ -1701,6 +1701,7 @@ int ieee802_1x_init(struct hostapd_data *hapd)
conf.wps = hapd->wps;
conf.fragment_size = hapd->conf->fragment_size;
conf.pwd_group = hapd->conf->pwd_group;
conf.pbc_in_m1 = hapd->conf->pbc_in_m1;
os_memset(&cb, 0, sizeof(cb));
cb.eapol_send = ieee802_1x_eapol_send;

View file

@ -110,6 +110,8 @@ struct eap_config {
const struct wpabuf *assoc_p2p_ie;
const u8 *peer_addr;
int fragment_size;
int pbc_in_m1;
};

View file

@ -192,6 +192,8 @@ struct eap_sm {
/* Fragmentation size for EAP method init() handler */
int fragment_size;
int pbc_in_m1;
};
int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,

View file

@ -1261,6 +1261,7 @@ struct eap_sm * eap_server_sm_init(void *eapol_ctx,
os_memcpy(sm->peer_addr, conf->peer_addr, ETH_ALEN);
sm->fragment_size = conf->fragment_size;
sm->pwd_group = conf->pwd_group;
sm->pbc_in_m1 = conf->pbc_in_m1;
wpa_printf(MSG_DEBUG, "EAP: Server state machine created");

View file

@ -144,6 +144,7 @@ static void * eap_wsc_init(struct eap_sm *sm)
cfg.p2p_dev_addr = p2p_get_go_dev_addr(sm->assoc_p2p_ie);
}
#endif /* CONFIG_P2P */
cfg.pbc_in_m1 = sm->pbc_in_m1;
data->wps = wps_init(&cfg);
if (data->wps == NULL) {
os_free(data);

View file

@ -834,6 +834,7 @@ eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
eap_conf.peer_addr = addr;
eap_conf.fragment_size = eapol->conf.fragment_size;
eap_conf.pwd_group = eapol->conf.pwd_group;
eap_conf.pbc_in_m1 = eapol->conf.pbc_in_m1;
sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf);
if (sm->eap == NULL) {
eapol_auth_free(sm);
@ -1039,6 +1040,7 @@ static int eapol_auth_conf_clone(struct eapol_auth_config *dst,
dst->eap_sim_db_priv = src->eap_sim_db_priv;
os_free(dst->eap_req_id_text);
dst->pwd_group = src->pwd_group;
dst->pbc_in_m1 = src->pbc_in_m1;
if (src->eap_req_id_text) {
dst->eap_req_id_text = os_malloc(src->eap_req_id_text_len);
if (dst->eap_req_id_text == NULL)

View file

@ -42,6 +42,7 @@ struct eapol_auth_config {
struct wps_context *wps;
int fragment_size;
u16 pwd_group;
int pbc_in_m1;
/* Opaque context pointer to owner data for callback functions */
void *ctx;

View file

@ -113,6 +113,7 @@ struct wps_data * wps_init(const struct wps_config *cfg)
os_memcpy(data->p2p_dev_addr, cfg->p2p_dev_addr, ETH_ALEN);
data->use_psk_key = cfg->use_psk_key;
data->pbc_in_m1 = cfg->pbc_in_m1;
return data;
}

View file

@ -187,6 +187,14 @@ struct wps_config {
* to %NULL to indicate the station does not have a P2P Device Address.
*/
const u8 *p2p_dev_addr;
/**
* pbc_in_m1 - Do not remove PushButton config method in M1 (AP)
*
* This can be used to enable a workaround to allow Windows 7 to use
* PBC with the AP.
*/
int pbc_in_m1;
};
struct wps_data * wps_init(const struct wps_config *cfg);

View file

@ -133,10 +133,17 @@ static struct wpabuf * wps_build_m1(struct wps_data *wps)
return NULL;
config_methods = wps->wps->config_methods;
if (wps->wps->ap) {
if (wps->wps->ap && !wps->pbc_in_m1 &&
(wps->dev_password_len != 0 ||
(config_methods & WPS_CONFIG_DISPLAY))) {
/*
* These are the methods that the AP supports as an Enrollee
* for adding external Registrars, so remove PushButton.
*
* As a workaround for Windows 7 mechanism for probing WPS
* capabilities from M1, leave PushButton option if no PIN
* method is available or if WPS configuration enables PBC
* workaround.
*/
config_methods &= ~WPS_CONFIG_PUSHBUTTON;
#ifdef CONFIG_WPS2

View file

@ -119,6 +119,7 @@ struct wps_data {
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 */
int pbc_in_m1;
};