diff options
author | Dmitry Shmidt <dimitrysh@google.com> | 2012-09-09 15:20:40 -0700 |
---|---|---|
committer | Dmitry Shmidt <dimitrysh@google.com> | 2012-09-10 09:26:29 -0700 |
commit | 4530cfd4d14a77c58e35393b91e40f8dd9d62697 (patch) | |
tree | 53014f1285c99fb848f49f93687f0b7b8836490e /wpa_supplicant | |
parent | 8367dc909f536f600c7474582fe0a96bef7c78fc (diff) | |
download | external_wpa_supplicant_8-4530cfd4d14a77c58e35393b91e40f8dd9d62697.zip external_wpa_supplicant_8-4530cfd4d14a77c58e35393b91e40f8dd9d62697.tar.gz external_wpa_supplicant_8-4530cfd4d14a77c58e35393b91e40f8dd9d62697.tar.bz2 |
wpa_supplicant: Update to 07-Sep-2012 TOT
commit 44256451130c4766e4a019162de17d0734444ee9
Author: Arik Nemtsov <arik@wizery.com>
Date: Fri Sep 7 00:22:40 2012 +0300
AP: Configure basic rates from iface and not conf
Skipped patches:
20ed5e40ba95440a1946cf2dffad3047fb620582
cf8baca6a5719f4f3257631e03317affee015417
a297201df15656dbb0f37e90f3410d9e8102c6fd
620c783753bddd37988269314862dc7e4a62f700
Change-Id: I857aa80af6d1a21b61f7c03a085e7dfc6066d61a
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'wpa_supplicant')
-rw-r--r-- | wpa_supplicant/Android.mk | 1 | ||||
-rw-r--r-- | wpa_supplicant/bss.c | 77 | ||||
-rw-r--r-- | wpa_supplicant/bss.h | 38 | ||||
-rw-r--r-- | wpa_supplicant/ctrl_iface.c | 24 | ||||
-rw-r--r-- | wpa_supplicant/eapol_test.c | 32 | ||||
-rw-r--r-- | wpa_supplicant/events.c | 4 | ||||
-rw-r--r-- | wpa_supplicant/hs20_supplicant.c | 28 | ||||
-rw-r--r-- | wpa_supplicant/interworking.c | 282 | ||||
-rw-r--r-- | wpa_supplicant/wpa_supplicant.conf | 3 | ||||
-rw-r--r-- | wpa_supplicant/wpa_supplicant_i.h | 1 | ||||
-rw-r--r-- | wpa_supplicant/wpas_glue.c | 41 |
11 files changed, 420 insertions, 111 deletions
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index eae00d8..4f58a92 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -1135,6 +1135,7 @@ SHA1OBJS += src/crypto/sha1-tlsprf.c endif endif +MD5OBJS = ifndef CONFIG_FIPS MD5OBJS += src/crypto/md5.c endif diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 580a82a..d326bef 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -35,6 +35,64 @@ #define WPA_BSS_IES_CHANGED_FLAG BIT(8) +static void wpa_bss_set_hessid(struct wpa_bss *bss) +{ +#ifdef CONFIG_INTERWORKING + const u8 *ie = wpa_bss_get_ie(bss, WLAN_EID_INTERWORKING); + if (ie == NULL || (ie[1] != 7 && ie[1] != 9)) { + os_memset(bss->hessid, 0, ETH_ALEN); + return; + } + if (ie[1] == 7) + os_memcpy(bss->hessid, ie + 3, ETH_ALEN); + else + os_memcpy(bss->hessid, ie + 5, ETH_ALEN); +#endif /* CONFIG_INTERWORKING */ +} + + +struct wpa_bss_anqp * wpa_bss_anqp_alloc(void) +{ + struct wpa_bss_anqp *anqp; + anqp = os_zalloc(sizeof(*anqp)); + if (anqp == NULL) + return NULL; + anqp->users = 1; + return anqp; +} + + +static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp) +{ + if (anqp == NULL) + return; + + anqp->users--; + if (anqp->users > 0) { + /* Another BSS entry holds a pointer to this ANQP info */ + return; + } + +#ifdef CONFIG_INTERWORKING + wpabuf_free(anqp->venue_name); + wpabuf_free(anqp->network_auth_type); + wpabuf_free(anqp->roaming_consortium); + wpabuf_free(anqp->ip_addr_type_availability); + wpabuf_free(anqp->nai_realm); + wpabuf_free(anqp->anqp_3gpp); + wpabuf_free(anqp->domain_name); +#endif /* CONFIG_INTERWORKING */ +#ifdef CONFIG_HS20 + wpabuf_free(anqp->hs20_operator_friendly_name); + wpabuf_free(anqp->hs20_wan_metrics); + wpabuf_free(anqp->hs20_connection_capability); + wpabuf_free(anqp->hs20_operating_class); +#endif /* CONFIG_HS20 */ + + os_free(anqp); +} + + static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, const char *reason) { @@ -45,21 +103,7 @@ static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, " SSID '%s' due to %s", bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len), reason); wpas_notify_bss_removed(wpa_s, bss->bssid, bss->id); -#ifdef CONFIG_INTERWORKING - wpabuf_free(bss->anqp_venue_name); - wpabuf_free(bss->anqp_network_auth_type); - wpabuf_free(bss->anqp_roaming_consortium); - wpabuf_free(bss->anqp_ip_addr_type_availability); - wpabuf_free(bss->anqp_nai_realm); - wpabuf_free(bss->anqp_3gpp); - wpabuf_free(bss->anqp_domain_name); -#endif /* CONFIG_INTERWORKING */ -#ifdef CONFIG_HS20 - wpabuf_free(bss->hs20_operator_friendly_name); - wpabuf_free(bss->hs20_wan_metrics); - wpabuf_free(bss->hs20_connection_capability); - wpabuf_free(bss->hs20_operating_class); -#endif /* CONFIG_HS20 */ + wpa_bss_anqp_free(bss->anqp); os_free(bss); } @@ -186,6 +230,7 @@ static void wpa_bss_add(struct wpa_supplicant *wpa_s, bss->ie_len = res->ie_len; bss->beacon_ie_len = res->beacon_ie_len; os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len); + wpa_bss_set_hessid(bss); dl_list_add_tail(&wpa_s->bss, &bss->list); dl_list_add_tail(&wpa_s->bss_id, &bss->list_id); @@ -365,6 +410,8 @@ static void wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, } dl_list_add(prev, &bss->list_id); } + if (changes & WPA_BSS_IES_CHANGED_FLAG) + wpa_bss_set_hessid(bss); dl_list_add_tail(&wpa_s->bss, &bss->list); notify_bss_changes(wpa_s, changes, bss); diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index 65e962b..8a307cc 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -19,6 +19,25 @@ struct wpa_scan_res; #define WPA_BSS_ASSOCIATED BIT(5) #define WPA_BSS_ANQP_FETCH_TRIED BIT(6) +struct wpa_bss_anqp { + unsigned int users; +#ifdef CONFIG_INTERWORKING + struct wpabuf *venue_name; + struct wpabuf *network_auth_type; + struct wpabuf *roaming_consortium; + struct wpabuf *ip_addr_type_availability; + struct wpabuf *nai_realm; + struct wpabuf *anqp_3gpp; + struct wpabuf *domain_name; +#endif /* CONFIG_INTERWORKING */ +#ifdef CONFIG_HS20 + struct wpabuf *hs20_operator_friendly_name; + struct wpabuf *hs20_wan_metrics; + struct wpabuf *hs20_connection_capability; + struct wpabuf *hs20_operating_class; +#endif /* CONFIG_HS20 */ +}; + /** * struct wpa_bss - BSS table * @list: List entry for struct wpa_supplicant::bss @@ -28,6 +47,7 @@ struct wpa_scan_res; * @flags: information flags about the BSS/IBSS (WPA_BSS_*) * @last_update_idx: Index of the last scan update * @bssid: BSSID + * @hessid: HESSID * @freq: frequency of the channel in MHz (e.g., 2412 = channel 1) * @beacon_int: beacon interval in TUs (host byte order) * @caps: capability information field in host byte order @@ -50,6 +70,7 @@ struct wpa_bss { unsigned int last_update_idx; unsigned int flags; u8 bssid[ETH_ALEN]; + u8 hessid[ETH_ALEN]; u8 ssid[32]; size_t ssid_len; int freq; @@ -60,21 +81,7 @@ struct wpa_bss { int level; u64 tsf; struct os_time last_update; -#ifdef CONFIG_INTERWORKING - struct wpabuf *anqp_venue_name; - struct wpabuf *anqp_network_auth_type; - struct wpabuf *anqp_roaming_consortium; - struct wpabuf *anqp_ip_addr_type_availability; - struct wpabuf *anqp_nai_realm; - struct wpabuf *anqp_3gpp; - struct wpabuf *anqp_domain_name; -#endif /* CONFIG_INTERWORKING */ -#ifdef CONFIG_HS20 - struct wpabuf *hs20_operator_friendly_name; - struct wpabuf *hs20_wan_metrics; - struct wpabuf *hs20_connection_capability; - struct wpabuf *hs20_operating_class; -#endif /* CONFIG_HS20 */ + struct wpa_bss_anqp *anqp; size_t ie_len; size_t beacon_ie_len; /* followed by ie_len octets of IEs */ @@ -103,5 +110,6 @@ struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss, u32 vendor_type); int wpa_bss_get_max_rate(const struct wpa_bss *bss); int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates); +struct wpa_bss_anqp * wpa_bss_anqp_alloc(void); #endif /* BSS_H */ diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 4f0c43d..480c077 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -2792,27 +2792,28 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, #endif /* CONFIG_WIFI_DISPLAY */ #ifdef CONFIG_INTERWORKING - if (mask & WPA_BSS_MASK_INTERNETW) { + if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) { + struct wpa_bss_anqp *anqp = bss->anqp; pos = anqp_add_hex(pos, end, "anqp_venue_name", - bss->anqp_venue_name); + anqp->venue_name); pos = anqp_add_hex(pos, end, "anqp_network_auth_type", - bss->anqp_network_auth_type); + anqp->network_auth_type); pos = anqp_add_hex(pos, end, "anqp_roaming_consortium", - bss->anqp_roaming_consortium); + anqp->roaming_consortium); pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability", - bss->anqp_ip_addr_type_availability); + anqp->ip_addr_type_availability); pos = anqp_add_hex(pos, end, "anqp_nai_realm", - bss->anqp_nai_realm); - pos = anqp_add_hex(pos, end, "anqp_3gpp", bss->anqp_3gpp); + anqp->nai_realm); + pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp); pos = anqp_add_hex(pos, end, "anqp_domain_name", - bss->anqp_domain_name); + anqp->domain_name); #ifdef CONFIG_HS20 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name", - bss->hs20_operator_friendly_name); + anqp->hs20_operator_friendly_name); pos = anqp_add_hex(pos, end, "hs20_wan_metrics", - bss->hs20_wan_metrics); + anqp->hs20_wan_metrics); pos = anqp_add_hex(pos, end, "hs20_connection_capability", - bss->hs20_connection_capability); + anqp->hs20_connection_capability); #endif /* CONFIG_HS20 */ } #endif /* CONFIG_INTERWORKING */ @@ -4381,6 +4382,7 @@ static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd, } #endif + char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, char *buf, size_t *resp_len) { diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c index 7d63c1b..03b8c7e 100644 --- a/wpa_supplicant/eapol_test.c +++ b/wpa_supplicant/eapol_test.c @@ -429,6 +429,37 @@ static void eapol_test_cert_cb(void *ctx, int depth, const char *subject, } +static void eapol_test_set_anon_id(void *ctx, const u8 *id, size_t len) +{ + struct eapol_test_data *e = ctx; + struct wpa_supplicant *wpa_s = e->wpa_s; + char *str; + int res; + + wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity", + id, len); + + if (wpa_s->current_ssid == NULL) + return; + + if (id == NULL) { + if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity", + "NULL", 0) < 0) + return; + } else { + str = os_malloc(len * 2 + 1); + if (str == NULL) + return; + wpa_snprintf_hex(str, len * 2 + 1, id, len); + res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity", + str, 0); + os_free(str); + if (res < 0) + return; + } +} + + static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { @@ -456,6 +487,7 @@ static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s, ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path; ctx->cert_cb = eapol_test_cert_cb; ctx->cert_in_cb = 1; + ctx->set_anon_id = eapol_test_set_anon_id; wpa_s->eapol = eapol_sm_init(ctx); if (wpa_s->eapol == NULL) { diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index c3acad4..bb870c0 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1062,6 +1062,9 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid = NULL; struct wpa_scan_results *scan_res; int ap = 0; +#ifndef CONFIG_NO_RANDOM_POOL + size_t i, num; +#endif /* CONFIG_NO_RANDOM_POOL */ #ifdef CONFIG_AP if (wpa_s->ap_iface) @@ -1100,7 +1103,6 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, } #ifndef CONFIG_NO_RANDOM_POOL - size_t i, num; num = scan_res->num; if (num > 10) num = 10; diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c index 2afa16c..0eb6119 100644 --- a/wpa_supplicant/hs20_supplicant.c +++ b/wpa_supplicant/hs20_supplicant.c @@ -110,10 +110,14 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s, const u8 *pos = data; u8 subtype; struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, sa); + struct wpa_bss_anqp *anqp = NULL; if (slen < 2) return; + if (bss) + anqp = bss->anqp; + subtype = *pos++; slen--; @@ -130,9 +134,9 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s, wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR " Operator Friendly Name", MAC2STR(sa)); wpa_hexdump_ascii(MSG_DEBUG, "oper friendly name", pos, slen); - if (bss) { - wpabuf_free(bss->hs20_operator_friendly_name); - bss->hs20_operator_friendly_name = + if (anqp) { + wpabuf_free(anqp->hs20_operator_friendly_name); + anqp->hs20_operator_friendly_name = wpabuf_alloc_copy(pos, slen); } break; @@ -140,18 +144,18 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s, wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR " WAN Metrics", MAC2STR(sa)); wpa_hexdump_ascii(MSG_DEBUG, "WAN Metrics", pos, slen); - if (bss) { - wpabuf_free(bss->hs20_wan_metrics); - bss->hs20_wan_metrics = wpabuf_alloc_copy(pos, slen); + if (anqp) { + wpabuf_free(anqp->hs20_wan_metrics); + anqp->hs20_wan_metrics = wpabuf_alloc_copy(pos, slen); } break; case HS20_STYPE_CONNECTION_CAPABILITY: wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR " Connection Capability", MAC2STR(sa)); wpa_hexdump_ascii(MSG_DEBUG, "conn capability", pos, slen); - if (bss) { - wpabuf_free(bss->hs20_connection_capability); - bss->hs20_connection_capability = + if (anqp) { + wpabuf_free(anqp->hs20_connection_capability); + anqp->hs20_connection_capability = wpabuf_alloc_copy(pos, slen); } break; @@ -159,9 +163,9 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s, wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR " Operating Class", MAC2STR(sa)); wpa_hexdump_ascii(MSG_DEBUG, "Operating Class", pos, slen); - if (bss) { - wpabuf_free(bss->hs20_operating_class); - bss->hs20_operating_class = + if (anqp) { + wpabuf_free(anqp->hs20_operating_class); + anqp->hs20_operating_class = wpabuf_alloc_copy(pos, slen); } break; diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index 7b5b20e..b362bcb 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -52,6 +52,18 @@ static void interworking_reconnect(struct wpa_supplicant *wpa_s) } wpa_s->disconnected = 0; wpa_s->reassociate = 1; + + if (wpa_s->last_scan_res_used > 0) { + struct os_time now; + os_get_time(&now); + if (now.sec - wpa_s->last_scan.sec <= 5) { + wpa_printf(MSG_DEBUG, "Interworking: Old scan results " + "are fresh - connect without new scan"); + if (wpas_select_network_from_last_scan(wpa_s) == 0) + return; + } + } + wpa_supplicant_req_scan(wpa_s, 0, 0); } @@ -96,27 +108,101 @@ static void interworking_anqp_resp_cb(void *ctx, const u8 *dst, } +static int cred_with_roaming_consortium(struct wpa_supplicant *wpa_s) +{ + struct wpa_cred *cred; + + for (cred = wpa_s->conf->cred; cred; cred = cred->next) { + if (cred->roaming_consortium_len) + return 1; + } + return 0; +} + + +static int cred_with_3gpp(struct wpa_supplicant *wpa_s) +{ + struct wpa_cred *cred; + + for (cred = wpa_s->conf->cred; cred; cred = cred->next) { + if (cred->pcsc || cred->imsi) + return 1; + } + return 0; +} + + +static int cred_with_nai_realm(struct wpa_supplicant *wpa_s) +{ + struct wpa_cred *cred; + + for (cred = wpa_s->conf->cred; cred; cred = cred->next) { + if (cred->pcsc || cred->imsi) + continue; + if (!cred->eap_method) + return 1; + if (cred->realm && cred->roaming_consortium_len == 0) + return 1; + } + return 0; +} + + +static int cred_with_domain(struct wpa_supplicant *wpa_s) +{ + struct wpa_cred *cred; + + for (cred = wpa_s->conf->cred; cred; cred = cred->next) { + if (cred->domain || cred->pcsc || cred->imsi) + return 1; + } + return 0; +} + + +static int additional_roaming_consortiums(struct wpa_bss *bss) +{ + const u8 *ie; + ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM); + if (ie == NULL || ie[1] == 0) + return 0; + return ie[2]; /* Number of ANQP OIs */ +} + + static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) { struct wpabuf *buf; int ret = 0; int res; - u16 info_ids[] = { - ANQP_CAPABILITY_LIST, - ANQP_VENUE_NAME, - ANQP_NETWORK_AUTH_TYPE, - ANQP_ROAMING_CONSORTIUM, - ANQP_IP_ADDR_TYPE_AVAILABILITY, - ANQP_NAI_REALM, - ANQP_3GPP_CELLULAR_NETWORK, - ANQP_DOMAIN_NAME - }; + u16 info_ids[8]; + size_t num_info_ids = 0; struct wpabuf *extra = NULL; + int all = wpa_s->fetch_all_anqp; wpa_printf(MSG_DEBUG, "Interworking: ANQP Query Request to " MACSTR, MAC2STR(bss->bssid)); + info_ids[num_info_ids++] = ANQP_CAPABILITY_LIST; + if (all) { + info_ids[num_info_ids++] = ANQP_VENUE_NAME; + info_ids[num_info_ids++] = ANQP_NETWORK_AUTH_TYPE; + } + if (all || (cred_with_roaming_consortium(wpa_s) && + additional_roaming_consortiums(bss))) + info_ids[num_info_ids++] = ANQP_ROAMING_CONSORTIUM; + if (all) + info_ids[num_info_ids++] = ANQP_IP_ADDR_TYPE_AVAILABILITY; + if (all || cred_with_nai_realm(wpa_s)) + info_ids[num_info_ids++] = ANQP_NAI_REALM; + if (all || cred_with_3gpp(wpa_s)) + info_ids[num_info_ids++] = ANQP_3GPP_CELLULAR_NETWORK; + if (all || cred_with_domain(wpa_s)) + info_ids[num_info_ids++] = ANQP_DOMAIN_NAME; + wpa_hexdump(MSG_DEBUG, "Interworking: ANQP Query info", + (u8 *) info_ids, num_info_ids * 2); + #ifdef CONFIG_HS20 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) { u8 *len_pos; @@ -131,16 +217,18 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s, wpabuf_put_u8(extra, HS20_STYPE_QUERY_LIST); wpabuf_put_u8(extra, 0); /* Reserved */ wpabuf_put_u8(extra, HS20_STYPE_CAPABILITY_LIST); - wpabuf_put_u8(extra, HS20_STYPE_OPERATOR_FRIENDLY_NAME); - wpabuf_put_u8(extra, HS20_STYPE_WAN_METRICS); - wpabuf_put_u8(extra, HS20_STYPE_CONNECTION_CAPABILITY); - wpabuf_put_u8(extra, HS20_STYPE_OPERATING_CLASS); + if (all) { + wpabuf_put_u8(extra, + HS20_STYPE_OPERATOR_FRIENDLY_NAME); + wpabuf_put_u8(extra, HS20_STYPE_WAN_METRICS); + wpabuf_put_u8(extra, HS20_STYPE_CONNECTION_CAPABILITY); + wpabuf_put_u8(extra, HS20_STYPE_OPERATING_CLASS); + } gas_anqp_set_element_len(extra, len_pos); } #endif /* CONFIG_HS20 */ - buf = anqp_build_req(info_ids, sizeof(info_ids) / sizeof(info_ids[0]), - extra); + buf = anqp_build_req(info_ids, num_info_ids, extra); wpabuf_free(extra); if (buf == NULL) return -1; @@ -648,8 +736,11 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s, struct wpa_cred *cred; struct wpa_ssid *ssid; const u8 *ie; + int eap_type; + int res; + char prefix; - if (bss->anqp_3gpp == NULL) + if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL) return -1; for (cred = wpa_s->conf->cred; cred; cred = cred->next) { @@ -680,7 +771,7 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s, #ifdef PCSC_FUNCS compare: #endif /* PCSC_FUNCS */ - if (plmn_id_match(bss->anqp_3gpp, imsi, mnc_len)) + if (plmn_id_match(bss->anqp->anqp_3gpp, imsi, mnc_len)) break; } if (cred == NULL) @@ -709,14 +800,40 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s, if (interworking_set_hs20_params(ssid) < 0) goto fail; - /* TODO: figure out whether to use EAP-SIM, EAP-AKA, or EAP-AKA' */ - if (wpa_config_set(ssid, "eap", "SIM", 0) < 0) { - wpa_printf(MSG_DEBUG, "EAP-SIM not supported"); + eap_type = EAP_TYPE_SIM; + if (cred->pcsc && wpa_s->scard && scard_supports_umts(wpa_s->scard)) + eap_type = EAP_TYPE_AKA; + if (cred->eap_method && cred->eap_method[0].vendor == EAP_VENDOR_IETF) { + if (cred->eap_method[0].method == EAP_TYPE_SIM || + cred->eap_method[0].method == EAP_TYPE_AKA || + cred->eap_method[0].method == EAP_TYPE_AKA_PRIME) + eap_type = cred->eap_method[0].method; + } + + switch (eap_type) { + case EAP_TYPE_SIM: + prefix = '1'; + res = wpa_config_set(ssid, "eap", "SIM", 0); + break; + case EAP_TYPE_AKA: + prefix = '0'; + res = wpa_config_set(ssid, "eap", "AKA", 0); + break; + case EAP_TYPE_AKA_PRIME: + prefix = '6'; + res = wpa_config_set(ssid, "eap", "AKA'", 0); + break; + default: + res = -1; + break; + } + if (res < 0) { + wpa_printf(MSG_DEBUG, "Selected EAP method (%d) not supported", + eap_type); goto fail; } - if (cred->pcsc && wpa_s->scard && scard_supports_umts(wpa_s->scard)) - wpa_config_set(ssid, "eap", "AKA", 0); - if (!cred->pcsc && set_root_nai(ssid, cred->imsi, '1') < 0) { + + if (!cred->pcsc && set_root_nai(ssid, cred->imsi, prefix) < 0) { wpa_printf(MSG_DEBUG, "Failed to set Root NAI"); goto fail; } @@ -835,7 +952,8 @@ static struct wpa_cred * interworking_credentials_available_roaming_consortium( ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM); - if (ie == NULL && bss->anqp_roaming_consortium == NULL) + if (ie == NULL && + (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL)) return NULL; if (wpa_s->conf->cred == NULL) @@ -845,7 +963,10 @@ static struct wpa_cred * interworking_credentials_available_roaming_consortium( if (cred->roaming_consortium_len == 0) continue; - if (!roaming_consortium_match(ie, bss->anqp_roaming_consortium, + if (!roaming_consortium_match(ie, + bss->anqp ? + bss->anqp->roaming_consortium : + NULL, cred->roaming_consortium, cred->roaming_consortium_len)) continue; @@ -1035,7 +1156,8 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) return interworking_connect_roaming_consortium(wpa_s, cred, bss, ie); - realm = nai_realm_parse(bss->anqp_nai_realm, &count); + realm = nai_realm_parse(bss->anqp ? bss->anqp->nai_realm : NULL, + &count); if (realm == NULL) { wpa_printf(MSG_DEBUG, "Interworking: Could not parse NAI " "Realm list from " MACSTR, MAC2STR(bss->bssid)); @@ -1162,7 +1284,7 @@ static struct wpa_cred * interworking_credentials_available_3gpp( int ret; #ifdef INTERWORKING_3GPP - if (bss->anqp_3gpp == NULL) + if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL) return NULL; for (cred = wpa_s->conf->cred; cred; cred = cred->next) { @@ -1195,7 +1317,7 @@ static struct wpa_cred * interworking_credentials_available_3gpp( #endif /* PCSC_FUNCS */ wpa_printf(MSG_DEBUG, "Interworking: Parsing 3GPP info from " MACSTR, MAC2STR(bss->bssid)); - ret = plmn_id_match(bss->anqp_3gpp, imsi, mnc_len); + ret = plmn_id_match(bss->anqp->anqp_3gpp, imsi, mnc_len); wpa_printf(MSG_DEBUG, "PLMN match %sfound", ret ? "" : "not "); if (ret) { if (selected == NULL || @@ -1215,7 +1337,7 @@ static struct wpa_cred * interworking_credentials_available_realm( struct nai_realm *realm; u16 count, i; - if (bss->anqp_nai_realm == NULL) + if (bss->anqp == NULL || bss->anqp->nai_realm == NULL) return NULL; if (wpa_s->conf->cred == NULL) @@ -1223,7 +1345,7 @@ static struct wpa_cred * interworking_credentials_available_realm( wpa_printf(MSG_DEBUG, "Interworking: Parsing NAI Realm list from " MACSTR, MAC2STR(bss->bssid)); - realm = nai_realm_parse(bss->anqp_nai_realm, &count); + realm = nai_realm_parse(bss->anqp->nai_realm, &count); if (realm == NULL) { wpa_printf(MSG_DEBUG, "Interworking: Could not parse NAI " "Realm list from " MACSTR, MAC2STR(bss->bssid)); @@ -1319,11 +1441,13 @@ static int interworking_home_sp(struct wpa_supplicant *wpa_s, int mnc_len = 0; if (cred->imsi) imsi = cred->imsi; +#ifdef CONFIG_PCSC else if (cred->pcsc && wpa_s->conf->pcsc_reader && wpa_s->scard && wpa_s->imsi[0]) { imsi = wpa_s->imsi; mnc_len = wpa_s->mnc_len; } +#endif /* CONFIG_PCSC */ if (imsi && build_root_nai(nai, sizeof(nai), imsi, mnc_len, 0) == 0) { realm = os_strchr(nai, '@'); @@ -1402,7 +1526,8 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s) continue; } count++; - res = interworking_home_sp(wpa_s, bss->anqp_domain_name); + res = interworking_home_sp(wpa_s, bss->anqp ? + bss->anqp->domain_name : NULL); if (res > 0) type = "home"; else if (res == 0) @@ -1465,6 +1590,38 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s) } +static struct wpa_bss_anqp * +interworking_match_anqp_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) +{ + struct wpa_bss *other; + + if (is_zero_ether_addr(bss->hessid)) + return NULL; /* Cannot be in the same homegenous ESS */ + + dl_list_for_each(other, &wpa_s->bss, struct wpa_bss, list) { + if (other == bss) + continue; + if (other->anqp == NULL) + continue; + if (!(other->flags & WPA_BSS_ANQP_FETCH_TRIED)) + continue; + if (os_memcmp(bss->hessid, other->hessid, ETH_ALEN) != 0) + continue; + if (bss->ssid_len != other->ssid_len || + os_memcmp(bss->ssid, other->ssid, bss->ssid_len) != 0) + continue; + + wpa_printf(MSG_DEBUG, "Interworking: Share ANQP data with " + "already fetched BSSID " MACSTR " and " MACSTR, + MAC2STR(other->bssid), MAC2STR(bss->bssid)); + other->anqp->users++; + return other->anqp; + } + + return NULL; +} + + static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s) { struct wpa_bss *bss; @@ -1482,6 +1639,17 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s) continue; /* AP does not support Interworking */ if (!(bss->flags & WPA_BSS_ANQP_FETCH_TRIED)) { + if (bss->anqp == NULL) { + bss->anqp = interworking_match_anqp_info(wpa_s, + bss); + if (bss->anqp) { + /* Shared data already fetched */ + continue; + } + bss->anqp = wpa_bss_anqp_alloc(); + if (bss->anqp == NULL) + break; + } found++; bss->flags |= WPA_BSS_ANQP_FETCH_TRIED; wpa_msg(wpa_s, MSG_INFO, "Starting ANQP fetch for " @@ -1518,6 +1686,7 @@ int interworking_fetch_anqp(struct wpa_supplicant *wpa_s) return 0; wpa_s->network_select = 0; + wpa_s->fetch_all_anqp = 1; interworking_start_fetch_anqp(wpa_s); @@ -1576,10 +1745,14 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, { const u8 *pos = data; struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, sa); + struct wpa_bss_anqp *anqp = NULL; #ifdef CONFIG_HS20 u8 type; #endif /* CONFIG_HS20 */ + if (bss) + anqp = bss->anqp; + switch (info_id) { case ANQP_CAPABILITY_LIST: wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR @@ -1589,9 +1762,9 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR " Venue Name", MAC2STR(sa)); wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Venue Name", pos, slen); - if (bss) { - wpabuf_free(bss->anqp_venue_name); - bss->anqp_venue_name = wpabuf_alloc_copy(pos, slen); + if (anqp) { + wpabuf_free(anqp->venue_name); + anqp->venue_name = wpabuf_alloc_copy(pos, slen); } break; case ANQP_NETWORK_AUTH_TYPE: @@ -1600,10 +1773,9 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, MAC2STR(sa)); wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Network Authentication " "Type", pos, slen); - if (bss) { - wpabuf_free(bss->anqp_network_auth_type); - bss->anqp_network_auth_type = - wpabuf_alloc_copy(pos, slen); + if (anqp) { + wpabuf_free(anqp->network_auth_type); + anqp->network_auth_type = wpabuf_alloc_copy(pos, slen); } break; case ANQP_ROAMING_CONSORTIUM: @@ -1611,10 +1783,9 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, " Roaming Consortium list", MAC2STR(sa)); wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Roaming Consortium", pos, slen); - if (bss) { - wpabuf_free(bss->anqp_roaming_consortium); - bss->anqp_roaming_consortium = - wpabuf_alloc_copy(pos, slen); + if (anqp) { + wpabuf_free(anqp->roaming_consortium); + anqp->roaming_consortium = wpabuf_alloc_copy(pos, slen); } break; case ANQP_IP_ADDR_TYPE_AVAILABILITY: @@ -1623,9 +1794,9 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, MAC2STR(sa)); wpa_hexdump(MSG_MSGDUMP, "ANQP: IP Address Availability", pos, slen); - if (bss) { - wpabuf_free(bss->anqp_ip_addr_type_availability); - bss->anqp_ip_addr_type_availability = + if (anqp) { + wpabuf_free(anqp->ip_addr_type_availability); + anqp->ip_addr_type_availability = wpabuf_alloc_copy(pos, slen); } break; @@ -1633,9 +1804,9 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR " NAI Realm list", MAC2STR(sa)); wpa_hexdump_ascii(MSG_DEBUG, "ANQP: NAI Realm", pos, slen); - if (bss) { - wpabuf_free(bss->anqp_nai_realm); - bss->anqp_nai_realm = wpabuf_alloc_copy(pos, slen); + if (anqp) { + wpabuf_free(anqp->nai_realm); + anqp->nai_realm = wpabuf_alloc_copy(pos, slen); } break; case ANQP_3GPP_CELLULAR_NETWORK: @@ -1643,18 +1814,18 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, " 3GPP Cellular Network information", MAC2STR(sa)); wpa_hexdump_ascii(MSG_DEBUG, "ANQP: 3GPP Cellular Network", pos, slen); - if (bss) { - wpabuf_free(bss->anqp_3gpp); - bss->anqp_3gpp = wpabuf_alloc_copy(pos, slen); + if (anqp) { + wpabuf_free(anqp->anqp_3gpp); + anqp->anqp_3gpp = wpabuf_alloc_copy(pos, slen); } break; case ANQP_DOMAIN_NAME: wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR " Domain Name list", MAC2STR(sa)); wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: Domain Name", pos, slen); - if (bss) { - wpabuf_free(bss->anqp_domain_name); - bss->anqp_domain_name = wpabuf_alloc_copy(pos, slen); + if (anqp) { + wpabuf_free(anqp->domain_name); + anqp->domain_name = wpabuf_alloc_copy(pos, slen); } break; case ANQP_VENDOR_SPECIFIC: @@ -1760,6 +1931,7 @@ int interworking_select(struct wpa_supplicant *wpa_s, int auto_select) wpa_s->network_select = 1; wpa_s->auto_network_select = 0; wpa_s->auto_select = !!auto_select; + wpa_s->fetch_all_anqp = 0; wpa_printf(MSG_DEBUG, "Interworking: Start scan for network " "selection"); wpa_s->scan_res_handler = interworking_scan_res_handler; diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 2c07fd0..0b0ea88 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -586,7 +586,8 @@ fast_reauth=1 # EAP-PSK/PAX/SAKE/GPSK. # anonymous_identity: Anonymous identity string for EAP (to be used as the # unencrypted identity with EAP types that support different tunnelled -# identity, e.g., EAP-TTLS) +# identity, e.g., EAP-TTLS). This field can also be used with +# EAP-SIM/AKA/AKA' to store the pseudonym identity. # password: Password string for EAP. This field can include either the # plaintext password (using ASCII or hex string) or a NtPasswordHash # (16-byte MD4 hash of password) in hash:<32 hex digits> format. diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index fb8dba8..6011439 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -578,6 +578,7 @@ struct wpa_supplicant { unsigned int network_select:1; unsigned int auto_select:1; unsigned int auto_network_select:1; + unsigned int fetch_all_anqp:1; #endif /* CONFIG_INTERWORKING */ unsigned int drv_capa_known; diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index fb4fa22..6aa5205 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - Glue code to setup EAPOL and RSN modules - * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi> + * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -729,6 +729,44 @@ static void wpa_supplicant_status_cb(void *ctx, const char *status, wpas_notify_eap_status(wpa_s, status, parameter); } + + +static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len) +{ + struct wpa_supplicant *wpa_s = ctx; + char *str; + int res; + + wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity", + id, len); + + if (wpa_s->current_ssid == NULL) + return; + + if (id == NULL) { + if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity", + "NULL", 0) < 0) + return; + } else { + str = os_malloc(len * 2 + 1); + if (str == NULL) + return; + wpa_snprintf_hex(str, len * 2 + 1, id, len); + res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity", + str, 0); + os_free(str); + if (res < 0) + return; + } + + if (wpa_s->conf->update_config) { + res = wpa_config_write(wpa_s->confname, wpa_s->conf); + if (res) { + wpa_printf(MSG_DEBUG, "Failed to update config after " + "anonymous_id update"); + } + } +} #endif /* IEEE8021X_EAPOL */ @@ -761,6 +799,7 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) ctx->cb = wpa_supplicant_eapol_cb; ctx->cert_cb = wpa_supplicant_cert_cb; ctx->status_cb = wpa_supplicant_status_cb; + ctx->set_anon_id = wpa_supplicant_set_anon_id; ctx->cb_ctx = wpa_s; wpa_s->eapol = eapol_sm_init(ctx); if (wpa_s->eapol == NULL) { |