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) { } else if (os_strcmp(buf, "upc") == 0) {
os_free(bss->upc); os_free(bss->upc);
bss->upc = os_strdup(pos); bss->upc = os_strdup(pos);
} else if (os_strcmp(buf, "pbc_in_m1") == 0) {
bss->pbc_in_m1 = atoi(pos);
#endif /* CONFIG_WPS */ #endif /* CONFIG_WPS */
#ifdef CONFIG_P2P_MANAGER #ifdef CONFIG_P2P_MANAGER
} else if (os_strcmp(buf, "manage_p2p") == 0) { } 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 # virtual_push_button physical_push_button
#config_methods=label virtual_display virtual_push_button keypad #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 # Static access point PIN for initial configuration and adding Registrars
# If not set, hostapd will not allow external WPS Registrars to control the # 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 # 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; char *upc;
struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS]; struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
#endif /* CONFIG_WPS */ #endif /* CONFIG_WPS */
int pbc_in_m1;
#define P2P_ENABLED BIT(0) #define P2P_ENABLED BIT(0)
#define P2P_GROUP_OWNER BIT(1) #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.wps = hapd->wps;
conf.fragment_size = hapd->conf->fragment_size; conf.fragment_size = hapd->conf->fragment_size;
conf.pwd_group = hapd->conf->pwd_group; conf.pwd_group = hapd->conf->pwd_group;
conf.pbc_in_m1 = hapd->conf->pbc_in_m1;
os_memset(&cb, 0, sizeof(cb)); os_memset(&cb, 0, sizeof(cb));
cb.eapol_send = ieee802_1x_eapol_send; cb.eapol_send = ieee802_1x_eapol_send;

View file

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

View file

@ -192,6 +192,8 @@ struct eap_sm {
/* Fragmentation size for EAP method init() handler */ /* Fragmentation size for EAP method init() handler */
int fragment_size; int fragment_size;
int pbc_in_m1;
}; };
int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len, 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); os_memcpy(sm->peer_addr, conf->peer_addr, ETH_ALEN);
sm->fragment_size = conf->fragment_size; sm->fragment_size = conf->fragment_size;
sm->pwd_group = conf->pwd_group; sm->pwd_group = conf->pwd_group;
sm->pbc_in_m1 = conf->pbc_in_m1;
wpa_printf(MSG_DEBUG, "EAP: Server state machine created"); 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); cfg.p2p_dev_addr = p2p_get_go_dev_addr(sm->assoc_p2p_ie);
} }
#endif /* CONFIG_P2P */ #endif /* CONFIG_P2P */
cfg.pbc_in_m1 = sm->pbc_in_m1;
data->wps = wps_init(&cfg); data->wps = wps_init(&cfg);
if (data->wps == NULL) { if (data->wps == NULL) {
os_free(data); 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.peer_addr = addr;
eap_conf.fragment_size = eapol->conf.fragment_size; eap_conf.fragment_size = eapol->conf.fragment_size;
eap_conf.pwd_group = eapol->conf.pwd_group; 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); sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf);
if (sm->eap == NULL) { if (sm->eap == NULL) {
eapol_auth_free(sm); 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; dst->eap_sim_db_priv = src->eap_sim_db_priv;
os_free(dst->eap_req_id_text); os_free(dst->eap_req_id_text);
dst->pwd_group = src->pwd_group; dst->pwd_group = src->pwd_group;
dst->pbc_in_m1 = src->pbc_in_m1;
if (src->eap_req_id_text) { if (src->eap_req_id_text) {
dst->eap_req_id_text = os_malloc(src->eap_req_id_text_len); dst->eap_req_id_text = os_malloc(src->eap_req_id_text_len);
if (dst->eap_req_id_text == NULL) if (dst->eap_req_id_text == NULL)

View file

@ -42,6 +42,7 @@ struct eapol_auth_config {
struct wps_context *wps; struct wps_context *wps;
int fragment_size; int fragment_size;
u16 pwd_group; u16 pwd_group;
int pbc_in_m1;
/* Opaque context pointer to owner data for callback functions */ /* Opaque context pointer to owner data for callback functions */
void *ctx; 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); os_memcpy(data->p2p_dev_addr, cfg->p2p_dev_addr, ETH_ALEN);
data->use_psk_key = cfg->use_psk_key; data->use_psk_key = cfg->use_psk_key;
data->pbc_in_m1 = cfg->pbc_in_m1;
return data; return data;
} }

View file

@ -187,6 +187,14 @@ struct wps_config {
* to %NULL to indicate the station does not have a P2P Device Address. * to %NULL to indicate the station does not have a P2P Device Address.
*/ */
const u8 *p2p_dev_addr; 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); 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; return NULL;
config_methods = wps->wps->config_methods; 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 * These are the methods that the AP supports as an Enrollee
* for adding external Registrars, so remove PushButton. * 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; config_methods &= ~WPS_CONFIG_PUSHBUTTON;
#ifdef CONFIG_WPS2 #ifdef CONFIG_WPS2

View file

@ -119,6 +119,7 @@ struct wps_data {
int use_psk_key; int use_psk_key;
u8 p2p_dev_addr[ETH_ALEN]; /* P2P Device Address of the client or u8 p2p_dev_addr[ETH_ALEN]; /* P2P Device Address of the client or
* 00:00:00:00:00:00 if not a P2p client */ * 00:00:00:00:00:00 if not a P2p client */
int pbc_in_m1;
}; };