X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=wpa_supplicant%2Fwps_supplicant.c;h=9af6084949d13c1440d5f1b5bd95a9f636b3f9cd;hb=1e78e76961664775f58b139f8c6388cfa0485f3d;hp=c89479f7d4f71d264c4ee184dfd3b53c82a9128f;hpb=f86232838cf712377867cb42417c1613ab5dc425;p=android-x86%2Fexternal-wpa_supplicant_8.git diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index c89479f..9af6084 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -1,6 +1,6 @@ /* * wpa_supplicant / WPS integration - * Copyright (c) 2008-2012, Jouni Malinen + * Copyright (c) 2008-2013, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -84,6 +84,10 @@ int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s) !(wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { int disabled = wpa_s->current_ssid->disabled; unsigned int freq = wpa_s->assoc_freq; + struct wpa_bss *bss; + struct wpa_ssid *ssid = NULL; + int use_fast_assoc = 0; + wpa_printf(MSG_DEBUG, "WPS: Network configuration replaced - " "try to associate with the received credential " "(freq=%u)", freq); @@ -98,7 +102,26 @@ int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s) wpa_s->wps_freq = freq; wpa_s->normal_scans = 0; wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); + + wpa_printf(MSG_DEBUG, "WPS: Checking whether fast association " + "without a new scan can be used"); + bss = wpa_supplicant_pick_network(wpa_s, &ssid); + if (bss) { + struct wpabuf *wps; + struct wps_parse_attr attr; + + wps = wpa_bss_get_vendor_ie_multi(bss, + WPS_IE_VENDOR_TYPE); + if (wps && wps_parse_msg(wps, &attr) == 0 && + attr.wps_state && + *attr.wps_state == WPS_STATE_CONFIGURED) + use_fast_assoc = 1; + wpabuf_free(wps); + } + + if (!use_fast_assoc || + wpa_supplicant_fast_associate(wpa_s) != 1) + wpa_supplicant_req_scan(wpa_s, 0, 0); return 1; } @@ -871,9 +894,10 @@ static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid; struct wpa_bss *bss; + wpa_s->after_wps = 0; wpa_s->known_wps_freq = 0; if (bssid) { - bss = wpa_bss_get_bssid(wpa_s, bssid); + bss = wpa_bss_get_bssid_latest(wpa_s, bssid); if (bss && bss->freq > 0) { wpa_s->known_wps_freq = 1; wpa_s->wps_freq = bss->freq; @@ -1581,91 +1605,128 @@ int wpas_wps_er_add_pin(struct wpa_supplicant *wpa_s, const u8 *addr, const char *uuid, const char *pin) { u8 u[UUID_LEN]; - int any = 0; - - if (os_strcmp(uuid, "any") == 0) - any = 1; - else if (uuid_str2bin(uuid, u)) + const u8 *use_uuid = NULL; + u8 addr_buf[ETH_ALEN]; + + if (os_strcmp(uuid, "any") == 0) { + } else if (uuid_str2bin(uuid, u) == 0) { + use_uuid = u; + } else if (hwaddr_aton(uuid, addr_buf) == 0) { + use_uuid = wps_er_get_sta_uuid(wpa_s->wps_er, addr_buf); + if (use_uuid == NULL) + return -1; + } else return -1; return wps_registrar_add_pin(wpa_s->wps->registrar, addr, - any ? NULL : u, + use_uuid, (const u8 *) pin, os_strlen(pin), 300); } int wpas_wps_er_pbc(struct wpa_supplicant *wpa_s, const char *uuid) { - u8 u[UUID_LEN]; + u8 u[UUID_LEN], *use_uuid = NULL; + u8 addr[ETH_ALEN], *use_addr = NULL; - if (uuid_str2bin(uuid, u)) + if (uuid_str2bin(uuid, u) == 0) + use_uuid = u; + else if (hwaddr_aton(uuid, addr) == 0) + use_addr = addr; + else return -1; - return wps_er_pbc(wpa_s->wps_er, u); + return wps_er_pbc(wpa_s->wps_er, use_uuid, use_addr); } int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid, const char *pin) { - u8 u[UUID_LEN]; + u8 u[UUID_LEN], *use_uuid = NULL; + u8 addr[ETH_ALEN], *use_addr = NULL; - if (uuid_str2bin(uuid, u)) + if (uuid_str2bin(uuid, u) == 0) + use_uuid = u; + else if (hwaddr_aton(uuid, addr) == 0) + use_addr = addr; + else return -1; - return wps_er_learn(wpa_s->wps_er, u, (const u8 *) pin, + + return wps_er_learn(wpa_s->wps_er, use_uuid, use_addr, (const u8 *) pin, os_strlen(pin)); } -int wpas_wps_er_set_config(struct wpa_supplicant *wpa_s, const char *uuid, - int id) +static int wpas_wps_network_to_cred(struct wpa_ssid *ssid, + struct wps_credential *cred) { - u8 u[UUID_LEN]; - struct wpa_ssid *ssid; - struct wps_credential cred; - - if (uuid_str2bin(uuid, u)) - return -1; - ssid = wpa_config_get_network(wpa_s->conf, id); - if (ssid == NULL || ssid->ssid == NULL) - return -1; - - os_memset(&cred, 0, sizeof(cred)); + os_memset(cred, 0, sizeof(*cred)); if (ssid->ssid_len > 32) return -1; - os_memcpy(cred.ssid, ssid->ssid, ssid->ssid_len); - cred.ssid_len = ssid->ssid_len; + os_memcpy(cred->ssid, ssid->ssid, ssid->ssid_len); + cred->ssid_len = ssid->ssid_len; if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { - cred.auth_type = (ssid->proto & WPA_PROTO_RSN) ? + cred->auth_type = (ssid->proto & WPA_PROTO_RSN) ? WPS_AUTH_WPA2PSK : WPS_AUTH_WPAPSK; if (ssid->pairwise_cipher & WPA_CIPHER_CCMP) - cred.encr_type = WPS_ENCR_AES; + cred->encr_type = WPS_ENCR_AES; else - cred.encr_type = WPS_ENCR_TKIP; + cred->encr_type = WPS_ENCR_TKIP; if (ssid->passphrase) { - cred.key_len = os_strlen(ssid->passphrase); - if (cred.key_len >= 64) + cred->key_len = os_strlen(ssid->passphrase); + if (cred->key_len >= 64) return -1; - os_memcpy(cred.key, ssid->passphrase, cred.key_len); + os_memcpy(cred->key, ssid->passphrase, cred->key_len); } else if (ssid->psk_set) { - cred.key_len = 32; - os_memcpy(cred.key, ssid->psk, 32); + cred->key_len = 32; + os_memcpy(cred->key, ssid->psk, 32); } else return -1; } else { - cred.auth_type = WPS_AUTH_OPEN; - cred.encr_type = WPS_ENCR_NONE; + cred->auth_type = WPS_AUTH_OPEN; + cred->encr_type = WPS_ENCR_NONE; } - return wps_er_set_config(wpa_s->wps_er, u, &cred); + + return 0; +} + + +int wpas_wps_er_set_config(struct wpa_supplicant *wpa_s, const char *uuid, + int id) +{ + u8 u[UUID_LEN], *use_uuid = NULL; + u8 addr[ETH_ALEN], *use_addr = NULL; + struct wpa_ssid *ssid; + struct wps_credential cred; + + if (uuid_str2bin(uuid, u) == 0) + use_uuid = u; + else if (hwaddr_aton(uuid, addr) == 0) + use_addr = addr; + else + return -1; + ssid = wpa_config_get_network(wpa_s->conf, id); + if (ssid == NULL || ssid->ssid == NULL) + return -1; + + if (wpas_wps_network_to_cred(ssid, &cred) < 0) + return -1; + return wps_er_set_config(wpa_s->wps_er, use_uuid, use_addr, &cred); } int wpas_wps_er_config(struct wpa_supplicant *wpa_s, const char *uuid, const char *pin, struct wps_new_ap_settings *settings) { - u8 u[UUID_LEN]; + u8 u[UUID_LEN], *use_uuid = NULL; + u8 addr[ETH_ALEN], *use_addr = NULL; struct wps_credential cred; size_t len; - if (uuid_str2bin(uuid, u)) + if (uuid_str2bin(uuid, u) == 0) + use_uuid = u; + else if (hwaddr_aton(uuid, addr) == 0) + use_addr = addr; + else return -1; if (settings->ssid_hex == NULL || settings->auth == NULL || settings->encr == NULL || settings->key_hex == NULL) @@ -1704,8 +1765,8 @@ int wpas_wps_er_config(struct wpa_supplicant *wpa_s, const char *uuid, else return -1; - return wps_er_config(wpa_s->wps_er, u, (const u8 *) pin, - os_strlen(pin), &cred); + return wps_er_config(wpa_s->wps_er, use_uuid, use_addr, + (const u8 *) pin, os_strlen(pin), &cred); } @@ -1714,15 +1775,20 @@ struct wpabuf * wpas_wps_er_nfc_config_token(struct wpa_supplicant *wpa_s, int ndef, const char *uuid) { struct wpabuf *ret; - u8 u[UUID_LEN]; + u8 u[UUID_LEN], *use_uuid = NULL; + u8 addr[ETH_ALEN], *use_addr = NULL; if (!wpa_s->wps_er) return NULL; - if (uuid_str2bin(uuid, u)) + if (uuid_str2bin(uuid, u) == 0) + use_uuid = u; + else if (hwaddr_aton(uuid, addr) == 0) + use_addr = addr; + else return NULL; - ret = wps_er_nfc_config_token(wpa_s->wps_er, u); + ret = wps_er_nfc_config_token(wpa_s->wps_er, use_uuid, use_addr); if (ndef && ret) { struct wpabuf *tmp; tmp = ndef_build_wifi(ret); @@ -1830,9 +1896,52 @@ void wpas_wps_update_config(struct wpa_supplicant *wpa_s) #ifdef CONFIG_WPS_NFC +#ifdef CONFIG_WPS_ER +static struct wpabuf * +wpas_wps_network_config_token(struct wpa_supplicant *wpa_s, int ndef, + struct wpa_ssid *ssid) +{ + struct wpabuf *ret; + struct wps_credential cred; + + if (wpas_wps_network_to_cred(ssid, &cred) < 0) + return NULL; + + ret = wps_er_config_token_from_cred(wpa_s->wps, &cred); + + if (ndef && ret) { + struct wpabuf *tmp; + tmp = ndef_build_wifi(ret); + wpabuf_free(ret); + if (tmp == NULL) + return NULL; + ret = tmp; + } + + return ret; +} +#endif /* CONFIG_WPS_ER */ + + struct wpabuf * wpas_wps_nfc_config_token(struct wpa_supplicant *wpa_s, - int ndef) + int ndef, const char *id_str) { +#ifdef CONFIG_WPS_ER + if (id_str) { + int id; + char *end = NULL; + struct wpa_ssid *ssid; + + id = strtol(id_str, &end, 10); + if (end && *end) + return NULL; + + ssid = wpa_config_get_network(wpa_s->conf, id); + if (ssid == NULL) + return NULL; + return wpas_wps_network_config_token(wpa_s, ndef, ssid); + } +#endif /* CONFIG_WPS_ER */ #ifdef CONFIG_AP if (wpa_s->ap_iface) return wpas_ap_wps_nfc_config_token(wpa_s, ndef); @@ -1881,8 +1990,13 @@ int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid) return -1; } wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, wps->dh_pubkey); - if (wps->dh_ctx == NULL) + if (wps->dh_ctx == NULL) { + wpabuf_free(wps->dh_pubkey); + wps->dh_pubkey = NULL; + wpabuf_free(wps->dh_privkey); + wps->dh_privkey = NULL; return -1; + } wpa_snprintf_hex_uppercase(pw, sizeof(pw), wpabuf_head(wpa_s->conf->wps_nfc_dev_pw), @@ -2003,12 +2117,59 @@ struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s, int cr) } +#ifdef CONFIG_WPS_NFC +struct wpabuf * wpas_wps_er_nfc_handover_sel(struct wpa_supplicant *wpa_s, + int ndef, const char *uuid) +{ +#ifdef CONFIG_WPS_ER + struct wpabuf *ret; + u8 u[UUID_LEN], *use_uuid = NULL; + u8 addr[ETH_ALEN], *use_addr = NULL; + + if (!wpa_s->wps_er) + return NULL; + + if (uuid == NULL) + return NULL; + if (uuid_str2bin(uuid, u) == 0) + use_uuid = u; + else if (hwaddr_aton(uuid, addr) == 0) + use_addr = addr; + else + return NULL; + + /* + * Handover Select carrier record for WPS uses the same format as + * configuration token. + */ + ret = wps_er_nfc_config_token(wpa_s->wps_er, use_uuid, use_addr); + if (ndef && ret) { + struct wpabuf *tmp; + tmp = ndef_build_wifi(ret); + wpabuf_free(ret); + if (tmp == NULL) + return NULL; + ret = tmp; + } + + return ret; +#else /* CONFIG_WPS_ER */ + return NULL; +#endif /* CONFIG_WPS_ER */ +} +#endif /* CONFIG_WPS_NFC */ + + struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s, - int ndef, int cr) + int ndef, int cr, const char *uuid) { + struct wpabuf *ret; if (!cr) return NULL; - return wpas_ap_wps_nfc_handover_sel(wpa_s, ndef); + ret = wpas_ap_wps_nfc_handover_sel(wpa_s, ndef); + if (ret) + return ret; + return wpas_wps_er_nfc_handover_sel(wpa_s, ndef, uuid); }