interworking.c revision 4530cfd4d14a77c58e35393b91e40f8dd9d62697
11f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/* 21f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Interworking (IEEE 802.11u) 304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Copyright (c) 2011-2012, Qualcomm Atheros, Inc. 41f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 71f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 81f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 91f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "includes.h" 101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "common.h" 121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "common/ieee802_11_defs.h" 131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "common/gas.h" 141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "common/wpa_ctrl.h" 1504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "utils/pcsc_funcs.h" 161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "drivers/driver.h" 171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "eap_common/eap_defs.h" 1861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "eap_peer/eap.h" 191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "eap_peer/eap_methods.h" 201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "wpa_supplicant_i.h" 211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "config.h" 2204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "config_ssid.h" 231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "bss.h" 241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "scan.h" 251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "notify.h" 261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "gas_query.h" 2704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "hs20_supplicant.h" 281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "interworking.h" 291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#if defined(EAP_SIM) | defined(EAP_SIM_DYNAMIC) 321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define INTERWORKING_3GPP 331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#else 341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#if defined(EAP_AKA) | defined(EAP_AKA_DYNAMIC) 351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define INTERWORKING_3GPP 361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#else 371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#if defined(EAP_AKA_PRIME) | defined(EAP_AKA_PRIME_DYNAMIC) 381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define INTERWORKING_3GPP 391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif 401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif 411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif 421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s); 441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void interworking_reconnect(struct wpa_supplicant *wpa_s) 4704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 4804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->wpa_state >= WPA_AUTHENTICATING) { 4904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_supplicant_cancel_sched_scan(wpa_s); 5004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_supplicant_deauthenticate(wpa_s, 5104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt WLAN_REASON_DEAUTH_LEAVING); 5204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 5304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->disconnected = 0; 5404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->reassociate = 1; 554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (wpa_s->last_scan_res_used > 0) { 574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct os_time now; 584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_get_time(&now); 594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (now.sec - wpa_s->last_scan.sec <= 5) { 604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Old scan results " 614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "are fresh - connect without new scan"); 624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (wpas_select_network_from_last_scan(wpa_s) == 0) 634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 6704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_supplicant_req_scan(wpa_s, 0, 0); 6804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 6904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 7004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct wpabuf * anqp_build_req(u16 info_ids[], size_t num_ids, 721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *extra) 731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf; 751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t i; 761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *len_pos; 771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf = gas_anqp_build_initial_req(0, 4 + num_ids * 2 + 791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (extra ? wpabuf_len(extra) : 0)); 801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL) 811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len_pos = gas_anqp_add_element(buf, ANQP_QUERY_LIST); 841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < num_ids; i++) 851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_le16(buf, info_ids[i]); 861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt gas_anqp_set_element_len(buf, len_pos); 871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (extra) 881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_buf(buf, extra); 891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt gas_anqp_set_len(buf); 911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return buf; 931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_anqp_resp_cb(void *ctx, const u8 *dst, 971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 dialog_token, 981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt enum gas_query_result result, 991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct wpabuf *adv_proto, 1001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct wpabuf *resp, 1011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 status_code) 1021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_supplicant *wpa_s = ctx; 1041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt anqp_resp_cb(wpa_s, dst, dialog_token, result, adv_proto, resp, 1061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt status_code); 1071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_next_anqp_fetch(wpa_s); 1081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 1091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int cred_with_roaming_consortium(struct wpa_supplicant *wpa_s) 1124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_cred *cred; 1144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 1164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->roaming_consortium_len) 1174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 1; 1184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 1204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 1214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int cred_with_3gpp(struct wpa_supplicant *wpa_s) 1244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_cred *cred; 1264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 1284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->pcsc || cred->imsi) 1294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 1; 1304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 1324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 1334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int cred_with_nai_realm(struct wpa_supplicant *wpa_s) 1364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_cred *cred; 1384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 1404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->pcsc || cred->imsi) 1414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 1424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!cred->eap_method) 1434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 1; 1444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->realm && cred->roaming_consortium_len == 0) 1454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 1; 1464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 1484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 1494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int cred_with_domain(struct wpa_supplicant *wpa_s) 1524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_cred *cred; 1544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 1564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->domain || cred->pcsc || cred->imsi) 1574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 1; 1584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 1604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 1614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int additional_roaming_consortiums(struct wpa_bss *bss) 1644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt const u8 *ie; 1664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM); 1674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ie == NULL || ie[1] == 0) 1684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 1694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return ie[2]; /* Number of ANQP OIs */ 1704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 1714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int interworking_anqp_send_req(struct wpa_supplicant *wpa_s, 1741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_bss *bss) 1751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf; 1771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret = 0; 1781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int res; 1794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt u16 info_ids[8]; 1804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt size_t num_info_ids = 0; 1811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *extra = NULL; 1824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int all = wpa_s->fetch_all_anqp; 1831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: ANQP Query Request to " MACSTR, 1851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(bss->bssid)); 1861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_CAPABILITY_LIST; 1884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all) { 1894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_VENUE_NAME; 1904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_NETWORK_AUTH_TYPE; 1914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all || (cred_with_roaming_consortium(wpa_s) && 1934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt additional_roaming_consortiums(bss))) 1944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_ROAMING_CONSORTIUM; 1954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all) 1964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_IP_ADDR_TYPE_AVAILABILITY; 1974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all || cred_with_nai_realm(wpa_s)) 1984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_NAI_REALM; 1994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all || cred_with_3gpp(wpa_s)) 2004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_3GPP_CELLULAR_NETWORK; 2014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all || cred_with_domain(wpa_s)) 2024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_DOMAIN_NAME; 2034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "Interworking: ANQP Query info", 2044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt (u8 *) info_ids, num_info_ids * 2); 2054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 20604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_HS20 20704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) { 20804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 *len_pos; 20904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 21004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt extra = wpabuf_alloc(100); 21104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!extra) 21204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 21304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 21404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt len_pos = gas_anqp_add_element(extra, ANQP_VENDOR_SPECIFIC); 21504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_be24(extra, OUI_WFA); 21604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(extra, HS20_ANQP_OUI_TYPE); 21704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_QUERY_LIST); 21804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(extra, 0); /* Reserved */ 21904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_CAPABILITY_LIST); 2204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all) { 2214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_put_u8(extra, 2224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt HS20_STYPE_OPERATOR_FRIENDLY_NAME); 2234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_WAN_METRICS); 2244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_CONNECTION_CAPABILITY); 2254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_OPERATING_CLASS); 2264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 22704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt gas_anqp_set_element_len(extra, len_pos); 22804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 22904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_HS20 */ 23004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt buf = anqp_build_req(info_ids, num_info_ids, extra); 2321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_free(extra); 2331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL) 2341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 2351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, buf, 2371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_anqp_resp_cb, wpa_s); 2381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (res < 0) { 2391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request"); 2401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = -1; 2411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else 2421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token " 2431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "%u", res); 2441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_free(buf); 2461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ret; 2471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct nai_realm_eap { 2511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 method; 2521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 inner_method; 2531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt enum nai_realm_eap_auth_inner_non_eap inner_non_eap; 2541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 cred_type; 2551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 tunneled_cred_type; 2561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}; 2571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct nai_realm { 2591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 encoding; 2601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt char *realm; 2611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 eap_count; 2621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm_eap *eap; 2631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}; 2641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void nai_realm_free(struct nai_realm *realms, u16 count) 2671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 i; 2691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (realms == NULL) 2711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 2721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < count; i++) { 2731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(realms[i].eap); 2741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(realms[i].realm); 2751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(realms); 2771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic const u8 * nai_realm_parse_eap(struct nai_realm_eap *e, const u8 *pos, 2811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *end) 2821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 elen, auth_count, a; 2841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *e_end; 2851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + 3 > end) { 2871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for EAP Method fixed fields"); 2881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 2891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt elen = *pos++; 2921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + elen > end || elen < 2) { 2931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for EAP Method subfield"); 2941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 2951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e_end = pos + elen; 2971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->method = *pos++; 2981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt auth_count = *pos++; 2991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP Method: len=%u method=%u auth_count=%u", 3001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt elen, e->method, auth_count); 3011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (a = 0; a < auth_count; a++) { 3031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 id, len; 3041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + 2 > end || pos + 2 + pos[1] > end) { 3061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for Authentication " 3071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Parameter subfield"); 3081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 3091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt id = *pos++; 3121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = *pos++; 3131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (id) { 3151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_EAP_AUTH_NON_EAP_INNER_AUTH: 3161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < 1) 3171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->inner_non_eap = *pos; 3191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (e->method != EAP_TYPE_TTLS) 3201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (*pos) { 3221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_PAP: 3231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP"); 3241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_CHAP: 3261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP"); 3271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_MSCHAP: 3291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP"); 3301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_MSCHAPV2: 3321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2"); 3331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_EAP_AUTH_INNER_AUTH_EAP_METHOD: 3371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < 1) 3381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->inner_method = *pos; 3401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Inner EAP method: %u", 3411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->inner_method); 3421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_EAP_AUTH_CRED_TYPE: 3441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < 1) 3451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->cred_type = *pos; 3471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Credential Type: %u", 3481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->cred_type); 3491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_EAP_AUTH_TUNNELED_CRED_TYPE: 3511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < 1) 3521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->tunneled_cred_type = *pos; 3541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Tunneled EAP Method Credential " 3551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Type: %u", e->tunneled_cred_type); 3561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt default: 3581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Unsupported Authentication " 3591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Parameter: id=%u len=%u", id, len); 3601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump(MSG_DEBUG, "Authentication Parameter " 3611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Value", pos, len); 3621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += len; 3661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return e_end; 3691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 3701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic const u8 * nai_realm_parse_realm(struct nai_realm *r, const u8 *pos, 3731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *end) 3741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 3751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 len; 3761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *f_end; 3771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 realm_len, e; 3781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (end - pos < 4) { 3801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for NAI Realm Data " 3811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "fixed fields"); 3821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 3831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = WPA_GET_LE16(pos); /* NAI Realm Data field Length */ 3861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 3871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + len > end || len < 3) { 3881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for NAI Realm Data " 3891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "(len=%u; left=%u)", 3901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len, (unsigned int) (end - pos)); 3911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 3921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt f_end = pos + len; 3941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt r->encoding = *pos++; 3961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt realm_len = *pos++; 3971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + realm_len > f_end) { 3981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for NAI Realm " 3991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "(len=%u; left=%u)", 4001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt realm_len, (unsigned int) (f_end - pos)); 4011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "NAI Realm", pos, realm_len); 4041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt r->realm = os_malloc(realm_len + 1); 4051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (r->realm == NULL) 4061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(r->realm, pos, realm_len); 4081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt r->realm[realm_len] = '\0'; 4091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += realm_len; 4101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + 1 > f_end) { 4121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for EAP Method Count"); 4131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt r->eap_count = *pos++; 4161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP Count: %u", r->eap_count); 4171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + r->eap_count * 3 > f_end) { 4181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for EAP Methods"); 4191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 42161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt r->eap = os_calloc(r->eap_count, sizeof(struct nai_realm_eap)); 4221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (r->eap == NULL) 4231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (e = 0; e < r->eap_count; e++) { 4261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = nai_realm_parse_eap(&r->eap[e], pos, f_end); 4271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos == NULL) 4281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return f_end; 4321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 4331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct nai_realm * nai_realm_parse(struct wpabuf *anqp, u16 *count) 4361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 4371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm *realm; 4381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *pos, *end; 4391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 i, num; 4401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (anqp == NULL || wpabuf_len(anqp) < 2) 4421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = wpabuf_head_u8(anqp); 4451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = pos + wpabuf_len(anqp); 4461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt num = WPA_GET_LE16(pos); 4471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "NAI Realm Count: %u", num); 4481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 4491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (num * 5 > end - pos) { 4511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid NAI Realm Count %u - not " 4521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "enough data (%u octets) for that many realms", 4531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt num, (unsigned int) (end - pos)); 4541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 45761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt realm = os_calloc(num, sizeof(struct nai_realm)); 4581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (realm == NULL) 4591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < num; i++) { 4621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = nai_realm_parse_realm(&realm[i], pos, end); 4631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos == NULL) { 4641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, num); 4651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *count = num; 4701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return realm; 4711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 4721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int nai_realm_match(struct nai_realm *realm, const char *home_realm) 4751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 4761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt char *tmp, *pos, *end; 4771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int match = 0; 4781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (realm->realm == NULL || home_realm == NULL) 4801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 4811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_strchr(realm->realm, ';') == NULL) 4831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return os_strcasecmp(realm->realm, home_realm) == 0; 4841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt tmp = os_strdup(realm->realm); 4861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (tmp == NULL) 4871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 4881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = tmp; 4901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (*pos) { 4911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = os_strchr(pos, ';'); 4921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (end) 4931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *end = '\0'; 4941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_strcasecmp(pos, home_realm) == 0) { 4951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt match = 1; 4961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (end == NULL) 4991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 5001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = end + 1; 5011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(tmp); 5041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return match; 5061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 5071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int nai_realm_cred_username(struct nai_realm_eap *eap) 5101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 5111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap_get_name(EAP_VENDOR_IETF, eap->method) == NULL) 5121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; /* method not supported */ 5131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->method != EAP_TYPE_TTLS && eap->method != EAP_TYPE_PEAP) { 5151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Only tunneled methods with username/password supported */ 5161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 5171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->method == EAP_TYPE_PEAP && 5201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL) 5211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 5221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->method == EAP_TYPE_TTLS) { 5241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->inner_method == 0 && eap->inner_non_eap == 0) 5251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 5261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->inner_method && 5271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL) 5281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 5291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->inner_non_eap && 5301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_PAP && 5311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_CHAP && 5321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_MSCHAP && 5331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_MSCHAPV2) 5341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 5351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->inner_method && 5381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_method != EAP_TYPE_GTC && 5391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_method != EAP_TYPE_MSCHAPV2) 5401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 5411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 1; 5431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 5441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 54604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int nai_realm_cred_cert(struct nai_realm_eap *eap) 54704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 54804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (eap_get_name(EAP_VENDOR_IETF, eap->method) == NULL) 54904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; /* method not supported */ 55004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 55104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (eap->method != EAP_TYPE_TLS) { 55204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Only EAP-TLS supported for credential authentication */ 55304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 55404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 55504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 55604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 1; 55704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 55804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 55904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 56004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic struct nai_realm_eap * nai_realm_find_eap(struct wpa_cred *cred, 5611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm *realm) 5621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 5631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 e; 5641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 56504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred == NULL || 56604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->username == NULL || 56704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->username[0] == '\0' || 56804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ((cred->password == NULL || 56904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->password[0] == '\0') && 57004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (cred->private_key == NULL || 57104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->private_key[0] == '\0'))) 5721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 5731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (e = 0; e < realm->eap_count; e++) { 5751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm_eap *eap = &realm->eap[e]; 57604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->password && cred->password[0] && 57704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt nai_realm_cred_username(eap)) 57804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return eap; 57904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->private_key && cred->private_key[0] && 58004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt nai_realm_cred_cert(eap)) 5811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eap; 5821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 5851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 5861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef INTERWORKING_3GPP 5891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 59004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int plmn_id_match(struct wpabuf *anqp, const char *imsi, int mnc_len) 5911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 5921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 plmn[3]; 5931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *pos, *end; 5941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 udhl; 5951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* See Annex A of 3GPP TS 24.234 v8.1.0 for description */ 5971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt plmn[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4); 5981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt plmn[1] = imsi[2] - '0'; 59904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* default to MNC length 3 if unknown */ 60004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (mnc_len != 2) 6011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt plmn[1] |= (imsi[5] - '0') << 4; 6021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt else 6031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt plmn[1] |= 0xf0; 6041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt plmn[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4); 6051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (anqp == NULL) 6071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 6081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = wpabuf_head_u8(anqp); 6091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = pos + wpabuf_len(anqp); 6101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + 2 > end) 6111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 6121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (*pos != 0) { 6131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Unsupported GUD version 0x%x", *pos); 6141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 6151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos++; 6171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt udhl = *pos++; 6181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + udhl > end) { 6191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid UDHL"); 6201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 6211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = pos + udhl; 6231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (pos + 2 <= end) { 6251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 iei, len; 6261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *l_end; 6271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iei = *pos++; 6281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = *pos++ & 0x7f; 6291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + len > end) 6301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 6311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt l_end = pos + len; 6321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (iei == 0 && len > 0) { 6341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* PLMN List */ 6351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 num, i; 6361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt num = *pos++; 6371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < num; i++) { 6381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + 3 > end) 6391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 6401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_memcmp(pos, plmn, 3) == 0) 6411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 1; /* Found matching PLMN */ 64261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += 3; 6431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = l_end; 6471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 6501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 6511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 65304949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int build_root_nai(char *nai, size_t nai_len, const char *imsi, 65461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t mnc_len, char prefix) 6551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 6561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const char *sep, *msin; 65704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char *end, *pos; 6581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t msin_len, plmn_len; 6591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 6611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * TS 23.003, Clause 14 (3GPP to WLAN Interworking) 6621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Root NAI: 6631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * <aka:0|sim:1><IMSI>@wlan.mnc<MNC>.mcc<MCC>.3gppnetwork.org 6641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * <MNC> is zero-padded to three digits in case two-digit MNC is used 6651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 6661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (imsi == NULL || os_strlen(imsi) > 16) { 6681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No valid IMSI available"); 6691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 6701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sep = os_strchr(imsi, '-'); 67261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sep) { 67361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt plmn_len = sep - imsi; 67461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt msin = sep + 1; 67561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else if (mnc_len && os_strlen(imsi) >= 3 + mnc_len) { 67661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt plmn_len = 3 + mnc_len; 67761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt msin = imsi + plmn_len; 67861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else 6791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 6801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (plmn_len != 5 && plmn_len != 6) 6811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 6821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt msin_len = os_strlen(msin); 6831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = nai; 68504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt end = nai + nai_len; 68604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (prefix) 68704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *pos++ = prefix; 6881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(pos, imsi, plmn_len); 6891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += plmn_len; 6901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(pos, msin, msin_len); 6911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += msin_len; 6921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += os_snprintf(pos, end - pos, "@wlan.mnc"); 6931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (plmn_len == 5) { 6941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = '0'; 6951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = imsi[3]; 6961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = imsi[4]; 6971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 6981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = imsi[3]; 6991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = imsi[4]; 7001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = imsi[5]; 7011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += os_snprintf(pos, end - pos, ".mcc%c%c%c.3gppnetwork.org", 7031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt imsi[0], imsi[1], imsi[2]); 7041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 70504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 70604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 70704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 70804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 70904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int set_root_nai(struct wpa_ssid *ssid, const char *imsi, char prefix) 71004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 71104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char nai[100]; 71261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (build_root_nai(nai, sizeof(nai), imsi, 0, prefix) < 0) 71304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 7141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return wpa_config_set_quoted(ssid, "identity", nai); 7151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 7161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* INTERWORKING_3GPP */ 7181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int interworking_set_hs20_params(struct wpa_ssid *ssid) 72161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 72261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_config_set(ssid, "key_mgmt", "WPA-EAP", 0) < 0) 72361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 72461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_config_set(ssid, "proto", "RSN", 0) < 0) 72561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 72661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0) 72761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 72861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 72961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 73061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 73161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 7321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int interworking_connect_3gpp(struct wpa_supplicant *wpa_s, 7331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_bss *bss) 7341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 7351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef INTERWORKING_3GPP 73604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_cred *cred; 7371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_ssid *ssid; 7381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *ie; 7394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int eap_type; 7404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int res; 7414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt char prefix; 7421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL) 74404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 74504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 74604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 74704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char *sep; 74804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const char *imsi; 74904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int mnc_len; 75004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 75104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef PCSC_FUNCS 75204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->pcsc && wpa_s->conf->pcsc_reader && wpa_s->scard && 75304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->imsi[0]) { 75404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt imsi = wpa_s->imsi; 75504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt mnc_len = wpa_s->mnc_len; 75604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto compare; 75704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 75804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* PCSC_FUNCS */ 75904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 76004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->imsi == NULL || !cred->imsi[0] || 76104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->milenage == NULL || !cred->milenage[0]) 76204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 76304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 76404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sep = os_strchr(cred->imsi, '-'); 76504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (sep == NULL || 76604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (sep - cred->imsi != 5 && sep - cred->imsi != 6)) 76704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 76804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt mnc_len = sep - cred->imsi - 3; 76904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt imsi = cred->imsi; 77004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 77104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef PCSC_FUNCS 77204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt compare: 77304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* PCSC_FUNCS */ 7744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (plmn_id_match(bss->anqp->anqp_3gpp, imsi, mnc_len)) 77504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 77604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 77704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred == NULL) 77804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 77904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 7801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_SSID); 7811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ie == NULL) 7821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 7831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR " (3GPP)", 7841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(bss->bssid)); 7851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid = wpa_config_add_network(wpa_s->conf); 7871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ssid == NULL) 7881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 7891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpas_notify_network_added(wpa_s, ssid); 7911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_config_set_network_defaults(ssid); 79204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ssid->priority = cred->priority; 7931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid->temporary = 1; 7941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid->ssid = os_zalloc(ie[1] + 1); 7951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ssid->ssid == NULL) 7961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 7971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(ssid->ssid, ie + 2, ie[1]); 7981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid->ssid_len = ie[1]; 7991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 80061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (interworking_set_hs20_params(ssid) < 0) 80161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto fail; 80261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 8034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_type = EAP_TYPE_SIM; 8044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->pcsc && wpa_s->scard && scard_supports_umts(wpa_s->scard)) 8054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_type = EAP_TYPE_AKA; 8064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->eap_method && cred->eap_method[0].vendor == EAP_VENDOR_IETF) { 8074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->eap_method[0].method == EAP_TYPE_SIM || 8084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt cred->eap_method[0].method == EAP_TYPE_AKA || 8094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt cred->eap_method[0].method == EAP_TYPE_AKA_PRIME) 8104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_type = cred->eap_method[0].method; 8114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 8124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 8134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt switch (eap_type) { 8144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case EAP_TYPE_SIM: 8154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt prefix = '1'; 8164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt res = wpa_config_set(ssid, "eap", "SIM", 0); 8174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt break; 8184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case EAP_TYPE_AKA: 8194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt prefix = '0'; 8204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt res = wpa_config_set(ssid, "eap", "AKA", 0); 8214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt break; 8224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case EAP_TYPE_AKA_PRIME: 8234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt prefix = '6'; 8244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt res = wpa_config_set(ssid, "eap", "AKA'", 0); 8254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt break; 8264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt default: 8274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt res = -1; 8284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt break; 8294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 8304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (res < 0) { 8314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "Selected EAP method (%d) not supported", 8324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_type); 8331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 8341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 8354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 8364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!cred->pcsc && set_root_nai(ssid, cred->imsi, prefix) < 0) { 8371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to set Root NAI"); 8381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 8391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 8401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 84104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->milenage && cred->milenage[0]) { 8421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set_quoted(ssid, "password", 84304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->milenage) < 0) 8441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 84504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else if (cred->pcsc) { 8461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set_quoted(ssid, "pcsc", "") < 0) 8471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 84804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->conf->pcsc_pin && 84904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_config_set_quoted(ssid, "pin", wpa_s->conf->pcsc_pin) 85004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt < 0) 85104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto fail; 8521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 8531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 85404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->password && cred->password[0] && 85504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_config_set_quoted(ssid, "password", cred->password) < 0) 8561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 8571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 85804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_config_update_prio_list(wpa_s->conf); 85904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt interworking_reconnect(wpa_s); 8601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 8621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtfail: 8641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpas_notify_network_removed(wpa_s, ssid); 8651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_config_remove_network(wpa_s->conf, ssid->id); 8661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* INTERWORKING_3GPP */ 8671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 8681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 8691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 87161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int roaming_consortium_element_match(const u8 *ie, const u8 *rc_id, 87261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t rc_len) 87361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 87461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *pos, *end; 87561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 lens; 87661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 87761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ie == NULL) 87861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 87961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 88061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = ie + 2; 88161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt end = ie + 2 + ie[1]; 88261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 88361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Roaming Consortium element: 88461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Number of ANQP OIs 88561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * OI #1 and #2 lengths 88661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * OI #1, [OI #2], [OI #3] 88761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 88861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 88961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos + 2 > end) 89061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 89161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 89261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos++; /* skip Number of ANQP OIs */ 89361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt lens = *pos++; 89461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos + (lens & 0x0f) + (lens >> 4) > end) 89561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 89661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 89761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if ((lens & 0x0f) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0) 89861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 1; 89961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += lens & 0x0f; 90061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 90161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if ((lens >> 4) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0) 90261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 1; 90361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += lens >> 4; 90461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 90561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos < end && (size_t) (end - pos) == rc_len && 90661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcmp(pos, rc_id, rc_len) == 0) 90761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 1; 90861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 90961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 91061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 91161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 91261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 91361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int roaming_consortium_anqp_match(const struct wpabuf *anqp, 91461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *rc_id, size_t rc_len) 91561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 91661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *pos, *end; 91761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 len; 91861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 91961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (anqp == NULL) 92061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 92161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 92261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = wpabuf_head(anqp); 92361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt end = pos + wpabuf_len(anqp); 92461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 92561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Set of <OI Length, OI> duples */ 92661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt while (pos < end) { 92761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len = *pos++; 92861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos + len > end) 92961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 93061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (len == rc_len && os_memcmp(pos, rc_id, rc_len) == 0) 93161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 1; 93261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += len; 93361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 93461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 93561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 93661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 93761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 93861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 93961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int roaming_consortium_match(const u8 *ie, const struct wpabuf *anqp, 94061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *rc_id, size_t rc_len) 94161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 94261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return roaming_consortium_element_match(ie, rc_id, rc_len) || 94361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt roaming_consortium_anqp_match(anqp, rc_id, rc_len); 94461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 94561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 94661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 94761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic struct wpa_cred * interworking_credentials_available_roaming_consortium( 94861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_bss *bss) 94961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 95061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_cred *cred, *selected = NULL; 95161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *ie; 95261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 95361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM); 95461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 9554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ie == NULL && 9564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL)) 95761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return NULL; 95861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 95961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_s->conf->cred == NULL) 96061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return NULL; 96161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 96261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 96361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->roaming_consortium_len == 0) 96461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt continue; 96561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 9664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!roaming_consortium_match(ie, 9674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss->anqp ? 9684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss->anqp->roaming_consortium : 9694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt NULL, 97061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->roaming_consortium, 97161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->roaming_consortium_len)) 97261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt continue; 97361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 97461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (selected == NULL || 97561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt selected->priority < cred->priority) 97661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt selected = cred; 97761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 97861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 97961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return selected; 98061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 98161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 98261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 98361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int interworking_set_eap_params(struct wpa_ssid *ssid, 98461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_cred *cred, int ttls) 98561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 98661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->eap_method) { 98761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ttls = cred->eap_method->vendor == EAP_VENDOR_IETF && 98861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->eap_method->method == EAP_TYPE_TTLS; 98961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 99061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(ssid->eap.eap_methods); 99161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->eap.eap_methods = 99261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_malloc(sizeof(struct eap_method_type) * 2); 99361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ssid->eap.eap_methods == NULL) 99461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 99561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(ssid->eap.eap_methods, cred->eap_method, 99661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sizeof(*cred->eap_method)); 99761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->eap.eap_methods[1].vendor = EAP_VENDOR_IETF; 99861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->eap.eap_methods[1].method = EAP_TYPE_NONE; 99961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 100061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 100161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ttls && cred->username && cred->username[0]) { 100261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const char *pos; 100361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt char *anon; 100461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Use anonymous NAI in Phase 1 */ 100561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = os_strchr(cred->username, '@'); 100661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos) { 100761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t buflen = 9 + os_strlen(pos) + 1; 100861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anon = os_malloc(buflen); 100961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (anon == NULL) 101061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 101161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_snprintf(anon, buflen, "anonymous%s", pos); 101261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else if (cred->realm) { 101361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t buflen = 10 + os_strlen(cred->realm) + 1; 101461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anon = os_malloc(buflen); 101561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (anon == NULL) 101661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 101761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_snprintf(anon, buflen, "anonymous@%s", cred->realm); 101861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else { 101961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anon = os_strdup("anonymous"); 102061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (anon == NULL) 102161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 102261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 102361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_config_set_quoted(ssid, "anonymous_identity", anon) < 102461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 0) { 102561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(anon); 102661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 102761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 102861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(anon); 102961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 103061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 103161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->username && cred->username[0] && 103261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "identity", cred->username) < 0) 103361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 103461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 103561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->password && cred->password[0]) { 103661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->ext_password && 103761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set(ssid, "password", cred->password, 0) < 0) 103861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 103961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!cred->ext_password && 104061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "password", cred->password) < 104161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 0) 104261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 104361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 104461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 104561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->client_cert && cred->client_cert[0] && 104661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "client_cert", cred->client_cert) < 0) 104761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 104861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 104961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->private_key && cred->private_key[0] && 105061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "private_key", cred->private_key) < 0) 105161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 105261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 105361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->private_key_passwd && cred->private_key_passwd[0] && 105461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "private_key_passwd", 105561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->private_key_passwd) < 0) 105661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 105761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 105861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->phase1) { 105961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(ssid->eap.phase1); 106061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->eap.phase1 = os_strdup(cred->phase1); 106161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 106261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->phase2) { 106361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(ssid->eap.phase2); 106461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->eap.phase2 = os_strdup(cred->phase2); 106561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 106661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 106761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->ca_cert && cred->ca_cert[0] && 106861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "ca_cert", cred->ca_cert) < 0) 106961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 107061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 107161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 107261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 107361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 107461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 107561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int interworking_connect_roaming_consortium( 107661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_cred *cred, 107761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_bss *bss, const u8 *ssid_ie) 107861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 107961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_ssid *ssid; 108061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 108161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR " based on " 108261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "roaming consortium match", MAC2STR(bss->bssid)); 108361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 108461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid = wpa_config_add_network(wpa_s->conf); 108561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ssid == NULL) 108661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 108761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpas_notify_network_added(wpa_s, ssid); 108861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_network_defaults(ssid); 108961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->priority = cred->priority; 109061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->temporary = 1; 109161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->ssid = os_zalloc(ssid_ie[1] + 1); 109261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ssid->ssid == NULL) 109361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto fail; 109461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(ssid->ssid, ssid_ie + 2, ssid_ie[1]); 109561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->ssid_len = ssid_ie[1]; 109661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 109761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (interworking_set_hs20_params(ssid) < 0) 109861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto fail; 109961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 110061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->eap_method == NULL) { 110161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: No EAP method set for " 110261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "credential using roaming consortium"); 110361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto fail; 110461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 110561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 110661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (interworking_set_eap_params( 110761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid, cred, 110861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->eap_method->vendor == EAP_VENDOR_IETF && 110961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->eap_method->method == EAP_TYPE_TTLS) < 0) 111061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto fail; 111161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 111261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_update_prio_list(wpa_s->conf); 111361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt interworking_reconnect(wpa_s); 111461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 111561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 111661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 111761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtfail: 111861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpas_notify_network_removed(wpa_s, ssid); 111961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_remove_network(wpa_s->conf, ssid->id); 112061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 112161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 112261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 112361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 11241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) 11251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 112604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_cred *cred; 11271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_ssid *ssid; 11281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm *realm; 11291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm_eap *eap = NULL; 11301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 count, i; 11311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt char buf[100]; 11321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *ie; 11331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 113404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->conf->cred == NULL || bss == NULL) 11351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 11361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_SSID); 11371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ie == NULL || ie[1] == 0) { 11381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: No SSID known for " 11391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 11401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 11411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 11421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 114361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) { 114461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 114561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * We currently support only HS 2.0 networks and those are 114661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * required to use WPA2-Enterprise. 114761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 114861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Network does not use " 114961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "RSN"); 115061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 115161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 115261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 115361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred = interworking_credentials_available_roaming_consortium(wpa_s, 115461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt bss); 115561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred) 115661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return interworking_connect_roaming_consortium(wpa_s, cred, 115761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt bss, ie); 115861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 11594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt realm = nai_realm_parse(bss->anqp ? bss->anqp->nai_realm : NULL, 11604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt &count); 11611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (realm == NULL) { 11621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Could not parse NAI " 11631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Realm list from " MACSTR, MAC2STR(bss->bssid)); 11641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt count = 0; 11651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 11661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 116704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 116804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0; i < count; i++) { 116904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!nai_realm_match(&realm[i], cred->realm)) 117004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 117104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap = nai_realm_find_eap(cred, &realm[i]); 117204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (eap) 117304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 117404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 11751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap) 11761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 11771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 11781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 11791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!eap) { 11801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (interworking_connect_3gpp(wpa_s, bss) == 0) { 11811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (realm) 11821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, count); 11831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 11841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 11851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 11861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: No matching credentials " 11871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "and EAP method found for " MACSTR, 11881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(bss->bssid)); 11891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, count); 11901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 11911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 11921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 11931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR, 11941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(bss->bssid)); 11951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 11961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid = wpa_config_add_network(wpa_s->conf); 11971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ssid == NULL) { 11981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, count); 11991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 12001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 12011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpas_notify_network_added(wpa_s, ssid); 12021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_config_set_network_defaults(ssid); 120304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ssid->priority = cred->priority; 12041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid->temporary = 1; 12051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid->ssid = os_zalloc(ie[1] + 1); 12061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ssid->ssid == NULL) 12071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 12081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(ssid->ssid, ie + 2, ie[1]); 12091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid->ssid_len = ie[1]; 12101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 121161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (interworking_set_hs20_params(ssid) < 0) 121204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto fail; 121304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 121461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_config_set(ssid, "eap", eap_get_name(EAP_VENDOR_IETF, 121561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt eap->method), 0) < 0) 12161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 12171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 12181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (eap->method) { 12191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case EAP_TYPE_TTLS: 12201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->inner_method) { 12211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_snprintf(buf, sizeof(buf), "\"autheap=%s\"", 12221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_get_name(EAP_VENDOR_IETF, 12231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_method)); 12241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set(ssid, "phase2", buf, 0) < 0) 12251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 12261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 12271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 12281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (eap->inner_non_eap) { 12291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_PAP: 12301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set(ssid, "phase2", "\"auth=PAP\"", 0) < 12311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 0) 12321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 12331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 12341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_CHAP: 12351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set(ssid, "phase2", "\"auth=CHAP\"", 0) 12361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt < 0) 12371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 12381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 12391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_MSCHAP: 1240c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAP\"", 1241c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 0) < 0) 12421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 12431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 12441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_MSCHAPV2: 12451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAPV2\"", 12461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 0) < 0) 12471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 12481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 12491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 12501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 12511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case EAP_TYPE_PEAP: 12521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_snprintf(buf, sizeof(buf), "\"auth=%s\"", 12531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_get_name(EAP_VENDOR_IETF, eap->inner_method)); 12541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set(ssid, "phase2", buf, 0) < 0) 12551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 12561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 125704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case EAP_TYPE_TLS: 125804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 12591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 12601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 126161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (interworking_set_eap_params(ssid, cred, 126261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt eap->method == EAP_TYPE_TTLS) < 0) 12631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 12641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 12651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, count); 12661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 126704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_config_update_prio_list(wpa_s->conf); 126804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt interworking_reconnect(wpa_s); 12691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 12701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 12711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 12721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtfail: 12731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpas_notify_network_removed(wpa_s, ssid); 12741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_config_remove_network(wpa_s->conf, ssid->id); 12751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, count); 12761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 12771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 12781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 12791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 128004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic struct wpa_cred * interworking_credentials_available_3gpp( 12811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_bss *bss) 12821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 128304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_cred *cred, *selected = NULL; 128404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int ret; 12851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 12861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef INTERWORKING_3GPP 12874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL) 128804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 12891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 129004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 129104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char *sep; 129204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const char *imsi; 129304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int mnc_len; 129404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 129504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef PCSC_FUNCS 129604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->pcsc && wpa_s->conf->pcsc_reader && wpa_s->scard && 129704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->imsi[0]) { 129804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt imsi = wpa_s->imsi; 129904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt mnc_len = wpa_s->mnc_len; 130004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto compare; 130104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 130204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* PCSC_FUNCS */ 13031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 130404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->imsi == NULL || !cred->imsi[0] || 130504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->milenage == NULL || !cred->milenage[0]) 130604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 130704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 130804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sep = os_strchr(cred->imsi, '-'); 130904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (sep == NULL || 131004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (sep - cred->imsi != 5 && sep - cred->imsi != 6)) 131104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 131204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt mnc_len = sep - cred->imsi - 3; 131304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt imsi = cred->imsi; 131404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 131504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef PCSC_FUNCS 131604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt compare: 131704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* PCSC_FUNCS */ 131804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Parsing 3GPP info from " 131904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 13204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt ret = plmn_id_match(bss->anqp->anqp_3gpp, imsi, mnc_len); 132104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "PLMN match %sfound", ret ? "" : "not "); 132204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (ret) { 132304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (selected == NULL || 132404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt selected->priority < cred->priority) 132504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt selected = cred; 132604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 132704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 13281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* INTERWORKING_3GPP */ 132904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return selected; 13301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 13311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 133304949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic struct wpa_cred * interworking_credentials_available_realm( 13341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_bss *bss) 13351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 133604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_cred *cred, *selected = NULL; 13371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm *realm; 13381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 count, i; 13391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp == NULL || bss->anqp->nai_realm == NULL) 134104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 13421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 134304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->conf->cred == NULL) 134404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 13451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Parsing NAI Realm list from " 13471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 13484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt realm = nai_realm_parse(bss->anqp->nai_realm, &count); 13491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (realm == NULL) { 13501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Could not parse NAI " 13511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Realm list from " MACSTR, MAC2STR(bss->bssid)); 135204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 13531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 13541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 135504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 135604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->realm == NULL) 13571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt continue; 135804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 135904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0; i < count; i++) { 136004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!nai_realm_match(&realm[i], cred->realm)) 136104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 136204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (nai_realm_find_eap(cred, &realm[i])) { 136304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (selected == NULL || 136404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt selected->priority < cred->priority) 136504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt selected = cred; 136604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 136704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 13681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 13691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 13701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, count); 13721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 137304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return selected; 137404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 137504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 137604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 137704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic struct wpa_cred * interworking_credentials_available( 137804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_bss *bss) 137904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 138004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_cred *cred, *cred2; 138104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 138204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred = interworking_credentials_available_realm(wpa_s, bss); 138304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred2 = interworking_credentials_available_3gpp(wpa_s, bss); 138404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred && cred2 && cred2->priority >= cred->priority) 138504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred = cred2; 138604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!cred) 138704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred = cred2; 138804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 138961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred2 = interworking_credentials_available_roaming_consortium(wpa_s, 139061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt bss); 139161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred && cred2 && cred2->priority >= cred->priority) 139261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred = cred2; 139361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!cred) 139461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred = cred2; 139561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 139604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return cred; 13971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 13981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 140004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int domain_name_list_contains(struct wpabuf *domain_names, 140104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const char *domain) 14021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 140304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *pos, *end; 140404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt size_t len; 140504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 140604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt len = os_strlen(domain); 140704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos = wpabuf_head(domain_names); 140804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt end = pos + wpabuf_len(domain_names); 140904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 141004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt while (pos + 1 < end) { 141104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (pos + 1 + pos[0] > end) 141204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 141304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 141404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "Interworking: AP domain name", 141504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos + 1, pos[0]); 141604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (pos[0] == len && 141704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_strncasecmp(domain, (const char *) (pos + 1), len) == 0) 141804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 1; 141904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 142004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += 1 + pos[0]; 142104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 142204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 142304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 142404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 142504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 142604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 142704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int interworking_home_sp(struct wpa_supplicant *wpa_s, 142804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf *domain_names) 142904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 143004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_cred *cred; 143104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef INTERWORKING_3GPP 143204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char nai[100], *realm; 143304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* INTERWORKING_3GPP */ 143404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 143504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (domain_names == NULL || wpa_s->conf->cred == NULL) 143604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 143704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 143804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 143904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef INTERWORKING_3GPP 144061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt char *imsi = NULL; 144161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int mnc_len = 0; 144261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->imsi) 144361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt imsi = cred->imsi; 14444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_PCSC 144561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt else if (cred->pcsc && wpa_s->conf->pcsc_reader && 144661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_s->scard && wpa_s->imsi[0]) { 144761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt imsi = wpa_s->imsi; 144861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt mnc_len = wpa_s->mnc_len; 144961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 14504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_PCSC */ 145161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (imsi && build_root_nai(nai, sizeof(nai), imsi, mnc_len, 0) 145261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt == 0) { 145304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt realm = os_strchr(nai, '@'); 145404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (realm) 145504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt realm++; 145604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Search for match " 145704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "with SIM/USIM domain %s", realm); 145804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (realm && 145904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt domain_name_list_contains(domain_names, realm)) 146004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 1; 146104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 146204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* INTERWORKING_3GPP */ 146304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 146404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->domain == NULL) 146504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 146604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 146704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Search for match with " 146804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "home SP FQDN %s", cred->domain); 146904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (domain_name_list_contains(domain_names, cred->domain)) 147004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 1; 147104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 147204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 147304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 147404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 147504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 147604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 147704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int interworking_find_network_match(struct wpa_supplicant *wpa_s) 147804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 147904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_bss *bss; 148004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_ssid *ssid; 148104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 148204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 148304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 148404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpas_network_disabled(wpa_s, ssid) || 148504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ssid->mode != WPAS_MODE_INFRA) 148604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 148704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (ssid->ssid_len != bss->ssid_len || 148804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) != 148904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 0) 149004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 149104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 149204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * TODO: Consider more accurate matching of security 149304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * configuration similarly to what is done in events.c 149404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 149504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 1; 149604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 149704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 149804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 149904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 15001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 15011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_select_network(struct wpa_supplicant *wpa_s) 15041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 150504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_bss *bss, *selected = NULL, *selected_home = NULL; 150604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int selected_prio = -999999, selected_home_prio = -999999; 15071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt unsigned int count = 0; 150804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const char *type; 150904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int res; 151004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_cred *cred; 15111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->network_select = 0; 15131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 151504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred = interworking_credentials_available(wpa_s, bss); 151604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!cred) 15171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt continue; 151861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) { 151961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 152061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * We currently support only HS 2.0 networks and those 152161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * are required to use WPA2-Enterprise. 152261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 152361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Credential match " 152461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "with " MACSTR " but network does not use " 152561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "RSN", MAC2STR(bss->bssid)); 152661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt continue; 152761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 15281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt count++; 15294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt res = interworking_home_sp(wpa_s, bss->anqp ? 15304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss->anqp->domain_name : NULL); 153104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (res > 0) 153204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt type = "home"; 153304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt else if (res == 0) 153404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt type = "roaming"; 153504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt else 153604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt type = "unknown"; 153704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, INTERWORKING_AP MACSTR " type=%s", 153804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt MAC2STR(bss->bssid), type); 153961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_s->auto_select || 154061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt (wpa_s->conf->auto_interworking && 154161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_s->auto_network_select)) { 154204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (selected == NULL || 154304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->priority > selected_prio) { 154404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt selected = bss; 154504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt selected_prio = cred->priority; 154604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 154704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (res > 0 && 154804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (selected_home == NULL || 154904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->priority > selected_home_prio)) { 155004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt selected_home = bss; 155104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt selected_home_prio = cred->priority; 155204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 155304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 155404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 155504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 155604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (selected_home && selected_home != selected && 155704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt selected_home_prio >= selected_prio) { 155804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Prefer network operated by the Home SP */ 155904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt selected = selected_home; 15601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 15611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (count == 0) { 156304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 156404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * No matching network was found based on configured 156504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * credentials. Check whether any of the enabled network blocks 156604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * have matching APs. 156704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 156804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (interworking_find_network_match(wpa_s)) { 156904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Possible BSS " 157004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "match for enabled network configurations"); 157161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_s->auto_select) 157261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt interworking_reconnect(wpa_s); 157361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 157461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 157561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 157661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_s->auto_network_select) { 157761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Continue " 157861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "scanning after ANQP fetch"); 157961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_supplicant_req_scan(wpa_s, wpa_s->scan_interval, 158061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 0); 158104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 158204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 158304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 15841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, INTERWORKING_NO_MATCH "No network " 15851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "with matching credentials found"); 15861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 15871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (selected) 15891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_connect(wpa_s, selected); 15901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 15911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 15934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic struct wpa_bss_anqp * 15944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtinterworking_match_anqp_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) 15954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 15964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_bss *other; 15974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 15984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (is_zero_ether_addr(bss->hessid)) 15994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return NULL; /* Cannot be in the same homegenous ESS */ 16004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 16014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt dl_list_for_each(other, &wpa_s->bss, struct wpa_bss, list) { 16024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (other == bss) 16034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 16044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (other->anqp == NULL) 16054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 16064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!(other->flags & WPA_BSS_ANQP_FETCH_TRIED)) 16074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 16084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (os_memcmp(bss->hessid, other->hessid, ETH_ALEN) != 0) 16094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 16104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->ssid_len != other->ssid_len || 16114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_memcmp(bss->ssid, other->ssid, bss->ssid_len) != 0) 16124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 16134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 16144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Share ANQP data with " 16154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "already fetched BSSID " MACSTR " and " MACSTR, 16164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt MAC2STR(other->bssid), MAC2STR(bss->bssid)); 16174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt other->anqp->users++; 16184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return other->anqp; 16194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 16204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 16214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return NULL; 16224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 16234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 16244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 16251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s) 16261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 16271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_bss *bss; 16281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int found = 0; 16291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *ie; 16301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!wpa_s->fetch_anqp_in_progress) 16321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 16331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 16351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!(bss->caps & IEEE80211_CAP_ESS)) 16361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt continue; 16371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB); 16381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ie == NULL || ie[1] < 4 || !(ie[5] & 0x80)) 16391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt continue; /* AP does not support Interworking */ 16401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!(bss->flags & WPA_BSS_ANQP_FETCH_TRIED)) { 16424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp == NULL) { 16434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss->anqp = interworking_match_anqp_info(wpa_s, 16444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss); 16454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp) { 16464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Shared data already fetched */ 16474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 16484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 16494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss->anqp = wpa_bss_anqp_alloc(); 16504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp == NULL) 16514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt break; 16524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 16531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt found++; 16541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bss->flags |= WPA_BSS_ANQP_FETCH_TRIED; 16551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "Starting ANQP fetch for " 16561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 16571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_anqp_send_req(wpa_s, bss); 16581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 16591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 16601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 16611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (found == 0) { 16631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "ANQP fetch completed"); 16641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->fetch_anqp_in_progress = 0; 16651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->network_select) 16661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_select_network(wpa_s); 16671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 16681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 16691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 167161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid interworking_start_fetch_anqp(struct wpa_supplicant *wpa_s) 16721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 16731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_bss *bss; 16741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) 16761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bss->flags &= ~WPA_BSS_ANQP_FETCH_TRIED; 16771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->fetch_anqp_in_progress = 1; 16791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_next_anqp_fetch(wpa_s); 16801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 16811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint interworking_fetch_anqp(struct wpa_supplicant *wpa_s) 16841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 16851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) 16861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 16871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->network_select = 0; 16894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_s->fetch_all_anqp = 1; 16901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_start_fetch_anqp(wpa_s); 16921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 16941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 16951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s) 16981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 16991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!wpa_s->fetch_anqp_in_progress) 17001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 17011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->fetch_anqp_in_progress = 0; 17031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 17041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, 17071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 info_ids[], size_t num_ids) 17081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 17091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf; 17101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret = 0; 17111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int freq; 17121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_bss *bss; 17131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int res; 17141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt freq = wpa_s->assoc_freq; 17161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bss = wpa_bss_get_bssid(wpa_s, dst); 17171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (bss) 17181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt freq = bss->freq; 17191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (freq <= 0) 17201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 17211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Query Request to " MACSTR " for %u id(s)", 17231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(dst), (unsigned int) num_ids); 17241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf = anqp_build_req(info_ids, num_ids, NULL); 17261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL) 17271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 17281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s); 17301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (res < 0) { 17311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request"); 17321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = -1; 17331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else 17341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token " 17351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "%u", res); 17361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_free(buf); 17381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ret; 17391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 17401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, 17431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *sa, u16 info_id, 17441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *data, size_t slen) 17451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 17461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *pos = data; 17471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, sa); 17484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_bss_anqp *anqp = NULL; 174904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_HS20 175004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 type; 175104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_HS20 */ 17521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss) 17544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp = bss->anqp; 17554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 17561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (info_id) { 17571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_CAPABILITY_LIST: 17581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 17591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " ANQP Capability list", MAC2STR(sa)); 17601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 17611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_VENUE_NAME: 17621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 17631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " Venue Name", MAC2STR(sa)); 17641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Venue Name", pos, slen); 17654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 17664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->venue_name); 17674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->venue_name = wpabuf_alloc_copy(pos, slen); 17681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 17691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 17701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_NETWORK_AUTH_TYPE: 17711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 17721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " Network Authentication Type information", 17731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(sa)); 17741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Network Authentication " 17751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Type", pos, slen); 17764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 17774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->network_auth_type); 17784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->network_auth_type = wpabuf_alloc_copy(pos, slen); 17791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 17801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 17811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_ROAMING_CONSORTIUM: 17821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 17831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " Roaming Consortium list", MAC2STR(sa)); 17841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Roaming Consortium", 17851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos, slen); 17864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 17874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->roaming_consortium); 17884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->roaming_consortium = wpabuf_alloc_copy(pos, slen); 17891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 17901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 17911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_IP_ADDR_TYPE_AVAILABILITY: 17921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 17931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " IP Address Type Availability information", 17941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(sa)); 17951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "ANQP: IP Address Availability", 17961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos, slen); 17974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 17984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->ip_addr_type_availability); 17994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->ip_addr_type_availability = 18001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_alloc_copy(pos, slen); 18011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 18021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 18031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_NAI_REALM: 18041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 18051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " NAI Realm list", MAC2STR(sa)); 18061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "ANQP: NAI Realm", pos, slen); 18074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 18084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->nai_realm); 18094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->nai_realm = wpabuf_alloc_copy(pos, slen); 18101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 18111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 18121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_3GPP_CELLULAR_NETWORK: 18131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 18141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " 3GPP Cellular Network information", MAC2STR(sa)); 18151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "ANQP: 3GPP Cellular Network", 18161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos, slen); 18174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 18184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->anqp_3gpp); 18194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->anqp_3gpp = wpabuf_alloc_copy(pos, slen); 18201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 18211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 18221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_DOMAIN_NAME: 18231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 18241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " Domain Name list", MAC2STR(sa)); 18251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: Domain Name", pos, slen); 18264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 18274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->domain_name); 18284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->domain_name = wpabuf_alloc_copy(pos, slen); 18291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 18301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 18311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_VENDOR_SPECIFIC: 18321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (slen < 3) 18331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 18341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 18351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (WPA_GET_BE24(pos)) { 183604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_HS20 183704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case OUI_WFA: 183804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += 3; 183904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt slen -= 3; 184004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 184104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (slen < 1) 184204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 184304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt type = *pos++; 184404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt slen--; 184504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 184604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt switch (type) { 184704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case HS20_ANQP_OUI_TYPE: 184804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hs20_parse_rx_hs20_anqp_resp(wpa_s, sa, pos, 184904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt slen); 185004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 185104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt default: 185204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "HS20: Unsupported ANQP " 185304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "vendor type %u", type); 185404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 185504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 185604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 185704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_HS20 */ 18581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt default: 18591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Unsupported " 18601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "vendor-specific ANQP OUI %06x", 18611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_GET_BE24(pos)); 18621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 18631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 18641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 18651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt default: 18661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Unsupported ANQP Info ID " 18671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "%u", info_id); 18681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 18691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 18701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 18711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 18721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 18731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token, 18741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt enum gas_query_result result, 18751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct wpabuf *adv_proto, 18761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct wpabuf *resp, u16 status_code) 18771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 18781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_supplicant *wpa_s = ctx; 18791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *pos; 18801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *end; 18811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 info_id; 18821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 slen; 18831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 18841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (result != GAS_QUERY_SUCCESS) 18851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 18861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 18871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = wpabuf_head(adv_proto); 18881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpabuf_len(adv_proto) < 4 || pos[0] != WLAN_EID_ADV_PROTO || 18891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos[1] < 2 || pos[3] != ACCESS_NETWORK_QUERY_PROTOCOL) { 18901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Unexpected Advertisement " 18911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Protocol in response"); 18921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 18931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 18941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 18951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = wpabuf_head(resp); 18961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = pos + wpabuf_len(resp); 18971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 18981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (pos < end) { 18991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + 4 > end) { 19001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Invalid element"); 19011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 19021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 19031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt info_id = WPA_GET_LE16(pos); 19041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 19051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt slen = WPA_GET_LE16(pos); 19061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 19071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + slen > end) { 19081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Invalid element length " 19091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "for Info ID %u", info_id); 19101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 19111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 19121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_parse_rx_anqp_resp(wpa_s, dst, info_id, pos, 19131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt slen); 19141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += slen; 19151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 19161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 19171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_scan_res_handler(struct wpa_supplicant *wpa_s, 19201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_scan_results *scan_res) 19211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 19221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Scan results available - start " 19231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "ANQP fetch"); 19241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_start_fetch_anqp(wpa_s); 19251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 19261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint interworking_select(struct wpa_supplicant *wpa_s, int auto_select) 19291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 19301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_stop_fetch_anqp(wpa_s); 19311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->network_select = 1; 193261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_s->auto_network_select = 0; 19331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->auto_select = !!auto_select; 19344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_s->fetch_all_anqp = 0; 19351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Start scan for network " 19361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "selection"); 19371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->scan_res_handler = interworking_scan_res_handler; 19381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->scan_req = 2; 19391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_req_scan(wpa_s, 0, 0); 19401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 19421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 194361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 194461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 194561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, 194661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt enum gas_query_result result, 194761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const struct wpabuf *adv_proto, 194861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const struct wpabuf *resp, u16 status_code) 194961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 195061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_supplicant *wpa_s = ctx; 195161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 195261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, GAS_RESPONSE_INFO "addr=" MACSTR 195361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt " dialog_token=%d status_code=%d resp_len=%d", 195461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt MAC2STR(addr), dialog_token, status_code, 195561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt resp ? (int) wpabuf_len(resp) : -1); 195661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!resp) 195761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 195861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 195961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_free(wpa_s->last_gas_resp); 196061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_s->last_gas_resp = wpabuf_dup(resp); 196161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_s->last_gas_resp == NULL) 196261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 196361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(wpa_s->last_gas_addr, addr, ETH_ALEN); 196461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_s->last_gas_dialog_token = dialog_token; 196561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 196661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 196761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 196861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst, 196961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const struct wpabuf *adv_proto, 197061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const struct wpabuf *query) 197161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 197261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *buf; 197361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int ret = 0; 197461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int freq; 197561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_bss *bss; 197661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int res; 197761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t len; 197861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 query_resp_len_limit = 0, pame_bi = 0; 197961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 198061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt freq = wpa_s->assoc_freq; 198161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt bss = wpa_bss_get_bssid(wpa_s, dst); 198261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (bss) 198361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt freq = bss->freq; 198461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (freq <= 0) 198561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 198661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 198761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "GAS request to " MACSTR " (freq %d MHz)", 198861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt MAC2STR(dst), freq); 198961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "Advertisement Protocol ID", adv_proto); 199061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "GAS Query", query); 199161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 199261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len = 3 + wpabuf_len(adv_proto) + 2; 199361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (query) 199461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len += wpabuf_len(query); 199561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt buf = gas_build_initial_req(0, len); 199661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (buf == NULL) 199761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 199861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 199961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Advertisement Protocol IE */ 200061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO); 200161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, 1 + wpabuf_len(adv_proto)); /* Length */ 200261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, (query_resp_len_limit & 0x7f) | 200361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt (pame_bi ? 0x80 : 0)); 200461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(buf, adv_proto); 200561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 200661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* GAS Query */ 200761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (query) { 200861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, wpabuf_len(query)); 200961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(buf, query); 201061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else 201161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, 0); 201261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 201361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt res = gas_query_req(wpa_s->gas, dst, freq, buf, gas_resp_cb, wpa_s); 201461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (res < 0) { 201561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "GAS: Failed to send Query Request"); 201661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ret = -1; 201761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else 201861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "GAS: Query started with dialog token " 201961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "%u", res); 202061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 202161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_free(buf); 202261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return ret; 202361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 2024