11f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/* 21f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Interworking (IEEE 802.11u) 35460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt * Copyright (c) 2011-2013, Qualcomm Atheros, Inc. 4fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt * Copyright (c) 2011-2014, Jouni Malinen <j@w1.fi> 51f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 7c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 81f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 91f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "includes.h" 111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "common.h" 131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "common/ieee802_11_defs.h" 141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "common/gas.h" 151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "common/wpa_ctrl.h" 1604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "utils/pcsc_funcs.h" 17a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#include "utils/eloop.h" 181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "drivers/driver.h" 191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "eap_common/eap_defs.h" 2061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "eap_peer/eap.h" 211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "eap_peer/eap_methods.h" 22b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt#include "eapol_supp/eapol_supp_sm.h" 235460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt#include "rsn_supp/wpa.h" 241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "wpa_supplicant_i.h" 251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "config.h" 2604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "config_ssid.h" 271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "bss.h" 281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "scan.h" 291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "notify.h" 305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "driver_i.h" 311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "gas_query.h" 3204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "hs20_supplicant.h" 331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "interworking.h" 341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#if defined(EAP_SIM) | defined(EAP_SIM_DYNAMIC) 371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define INTERWORKING_3GPP 381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#else 391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#if defined(EAP_AKA) | defined(EAP_AKA_DYNAMIC) 401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define INTERWORKING_3GPP 411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#else 421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#if defined(EAP_AKA_PRIME) | defined(EAP_AKA_PRIME_DYNAMIC) 431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define INTERWORKING_3GPP 441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif 451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif 461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif 471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s); 49f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtstatic struct wpa_cred * interworking_credentials_available_realm( 50f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 51f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int *excluded); 52f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtstatic struct wpa_cred * interworking_credentials_available_3gpp( 53f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 54f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int *excluded); 55f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 56f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 57f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int cred_prio_cmp(const struct wpa_cred *a, const struct wpa_cred *b) 58f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 59f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (a->priority > b->priority) 60f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 61f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (a->priority < b->priority) 62f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return -1; 63f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (a->provisioning_sp == NULL || b->provisioning_sp == NULL || 64f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt os_strcmp(a->provisioning_sp, b->provisioning_sp) != 0) 65f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; 66f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (a->sp_priority < b->sp_priority) 67f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 68f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (a->sp_priority > b->sp_priority) 69f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return -1; 70f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; 71f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void interworking_reconnect(struct wpa_supplicant *wpa_s) 7504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 762f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt unsigned int tried; 772f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 7804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->wpa_state >= WPA_AUTHENTICATING) { 7904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_supplicant_cancel_sched_scan(wpa_s); 80203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt wpa_s->own_disconnect_req = 1; 8104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_supplicant_deauthenticate(wpa_s, 8204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt WLAN_REASON_DEAUTH_LEAVING); 8304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 8404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->disconnected = 0; 8504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->reassociate = 1; 862f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt tried = wpa_s->interworking_fast_assoc_tried; 872f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt wpa_s->interworking_fast_assoc_tried = 1; 884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 892f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (!tried && wpa_supplicant_fast_associate(wpa_s) >= 0) 904b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return; 914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 922f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt wpa_s->interworking_fast_assoc_tried = 0; 9304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_supplicant_req_scan(wpa_s, 0, 0); 9404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 9504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 9604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct wpabuf * anqp_build_req(u16 info_ids[], size_t num_ids, 981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *extra) 991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf; 1011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t i; 1021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *len_pos; 1031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf = gas_anqp_build_initial_req(0, 4 + num_ids * 2 + 1051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (extra ? wpabuf_len(extra) : 0)); 1061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL) 1071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 1081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len_pos = gas_anqp_add_element(buf, ANQP_QUERY_LIST); 1101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < num_ids; i++) 1111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_le16(buf, info_ids[i]); 1121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt gas_anqp_set_element_len(buf, len_pos); 1131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (extra) 1141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_buf(buf, extra); 1151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt gas_anqp_set_len(buf); 1171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return buf; 1191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 1201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_anqp_resp_cb(void *ctx, const u8 *dst, 1231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 dialog_token, 1241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt enum gas_query_result result, 1251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct wpabuf *adv_proto, 1261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct wpabuf *resp, 1271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 status_code) 1281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_supplicant *wpa_s = ctx; 1301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 131f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Response callback dst=" MACSTR 132f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt " dialog_token=%u result=%d status_code=%u", 133f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MAC2STR(dst), dialog_token, result, status_code); 1341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt anqp_resp_cb(wpa_s, dst, dialog_token, result, adv_proto, resp, 1351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt status_code); 1361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_next_anqp_fetch(wpa_s); 1371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 1381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int cred_with_roaming_consortium(struct wpa_supplicant *wpa_s) 1414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_cred *cred; 1434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 1454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->roaming_consortium_len) 1464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 1; 147051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (cred->required_roaming_consortium_len) 148051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 1; 1494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 1514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 1524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int cred_with_3gpp(struct wpa_supplicant *wpa_s) 1554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_cred *cred; 1574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 1594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->pcsc || cred->imsi) 1604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 1; 1614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 1634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 1644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int cred_with_nai_realm(struct wpa_supplicant *wpa_s) 1674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_cred *cred; 1694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 1714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->pcsc || cred->imsi) 1724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 1734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!cred->eap_method) 1744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 1; 1754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->realm && cred->roaming_consortium_len == 0) 1764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 1; 1774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 1794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 1804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int cred_with_domain(struct wpa_supplicant *wpa_s) 1834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_cred *cred; 1854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 187f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred->domain || cred->pcsc || cred->imsi || 188f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->roaming_partner) 189f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 190f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 191f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; 192f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 193f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 194f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 195f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_HS20 196f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 197f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int cred_with_min_backhaul(struct wpa_supplicant *wpa_s) 198f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 199f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred; 200f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 201f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 202f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred->min_dl_bandwidth_home || 203f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->min_ul_bandwidth_home || 204f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->min_dl_bandwidth_roaming || 205f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->min_ul_bandwidth_roaming) 2064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 1; 2074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 2084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 2094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 2104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 2114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 212f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int cred_with_conn_capab(struct wpa_supplicant *wpa_s) 213f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 214f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred; 215f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 216f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 217f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred->num_req_conn_capab) 218f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 219f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 220f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; 221f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 222f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 223f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_HS20 */ 224f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 225f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int additional_roaming_consortiums(struct wpa_bss *bss) 2274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 2284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt const u8 *ie; 2294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM); 2304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ie == NULL || ie[1] == 0) 2314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 2324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return ie[2]; /* Number of ANQP OIs */ 2334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 2344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 2354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 236a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic void interworking_continue_anqp(void *eloop_ctx, void *sock_ctx) 237a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{ 238a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt struct wpa_supplicant *wpa_s = eloop_ctx; 239a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt interworking_next_anqp_fetch(wpa_s); 240a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt} 241a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 242a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 2431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int interworking_anqp_send_req(struct wpa_supplicant *wpa_s, 2441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_bss *bss) 2451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf; 2471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret = 0; 2481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int res; 2494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt u16 info_ids[8]; 2504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt size_t num_info_ids = 0; 2511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *extra = NULL; 2524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int all = wpa_s->fetch_all_anqp; 2531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 254216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, "Interworking: ANQP Query Request to " MACSTR, 255216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt MAC2STR(bss->bssid)); 256444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_s->interworking_gas_bss = bss; 2571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_CAPABILITY_LIST; 2594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all) { 2604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_VENUE_NAME; 2614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_NETWORK_AUTH_TYPE; 2624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 2634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all || (cred_with_roaming_consortium(wpa_s) && 2644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt additional_roaming_consortiums(bss))) 2654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_ROAMING_CONSORTIUM; 2664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all) 2674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_IP_ADDR_TYPE_AVAILABILITY; 2684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all || cred_with_nai_realm(wpa_s)) 2694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_NAI_REALM; 270df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (all || cred_with_3gpp(wpa_s)) { 2714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_3GPP_CELLULAR_NETWORK; 272df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_supplicant_scard_init(wpa_s, NULL); 273df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 2744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all || cred_with_domain(wpa_s)) 2754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_DOMAIN_NAME; 2764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "Interworking: ANQP Query info", 2774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt (u8 *) info_ids, num_info_ids * 2); 2784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 27904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_HS20 28004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) { 28104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 *len_pos; 28204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 28304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt extra = wpabuf_alloc(100); 28404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!extra) 28504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 28604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 28704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt len_pos = gas_anqp_add_element(extra, ANQP_VENDOR_SPECIFIC); 28804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_be24(extra, OUI_WFA); 28904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(extra, HS20_ANQP_OUI_TYPE); 29004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_QUERY_LIST); 29104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(extra, 0); /* Reserved */ 29204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_CAPABILITY_LIST); 293f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (all) 2944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_put_u8(extra, 2954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt HS20_STYPE_OPERATOR_FRIENDLY_NAME); 296f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (all || cred_with_min_backhaul(wpa_s)) 2974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_WAN_METRICS); 298f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (all || cred_with_conn_capab(wpa_s)) 2994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_CONNECTION_CAPABILITY); 300f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (all) 3014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_OPERATING_CLASS); 302f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (all) 303f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_LIST); 30404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt gas_anqp_set_element_len(extra, len_pos); 30504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 30604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_HS20 */ 30704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 3084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt buf = anqp_build_req(info_ids, num_info_ids, extra); 3091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_free(extra); 3101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL) 3111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 3121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, buf, 3141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_anqp_resp_cb, wpa_s); 3151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (res < 0) { 316216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request"); 317051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpabuf_free(buf); 3181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = -1; 319a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt eloop_register_timeout(0, 0, interworking_continue_anqp, wpa_s, 320a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt NULL); 3211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else 322216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 323216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "ANQP: Query started with dialog token %u", res); 3241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ret; 3261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 3271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct nai_realm_eap { 3301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 method; 3311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 inner_method; 3321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt enum nai_realm_eap_auth_inner_non_eap inner_non_eap; 3331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 cred_type; 3341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 tunneled_cred_type; 3351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}; 3361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct nai_realm { 3381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 encoding; 3391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt char *realm; 3401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 eap_count; 3411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm_eap *eap; 3421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}; 3431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void nai_realm_free(struct nai_realm *realms, u16 count) 3461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 3471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 i; 3481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (realms == NULL) 3501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 3511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < count; i++) { 3521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(realms[i].eap); 3531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(realms[i].realm); 3541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(realms); 3561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 3571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic const u8 * nai_realm_parse_eap(struct nai_realm_eap *e, const u8 *pos, 3601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *end) 3611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 3621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 elen, auth_count, a; 3631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *e_end; 3641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 365d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (end - pos < 3) { 3661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for EAP Method fixed fields"); 3671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 3681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt elen = *pos++; 371d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (elen > end - pos || elen < 2) { 3721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for EAP Method subfield"); 3731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 3741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e_end = pos + elen; 3761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->method = *pos++; 3771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt auth_count = *pos++; 3781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP Method: len=%u method=%u auth_count=%u", 3791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt elen, e->method, auth_count); 3801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (a = 0; a < auth_count; a++) { 3821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 id, len; 3831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 384d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (end - pos < 2) { 385d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 386d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "No room for Authentication Parameter subfield header"); 3871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 3881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt id = *pos++; 3911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = *pos++; 392d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (len > end - pos) { 393d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_DEBUG, 394d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt "No room for Authentication Parameter subfield"); 395d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return NULL; 396d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 3971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (id) { 3991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_EAP_AUTH_NON_EAP_INNER_AUTH: 4001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < 1) 4011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->inner_non_eap = *pos; 4031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (e->method != EAP_TYPE_TTLS) 4041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (*pos) { 4061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_PAP: 4071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP"); 4081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_CHAP: 4101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP"); 4111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_MSCHAP: 4131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP"); 4141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_MSCHAPV2: 4161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2"); 4171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_EAP_AUTH_INNER_AUTH_EAP_METHOD: 4211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < 1) 4221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->inner_method = *pos; 4241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Inner EAP method: %u", 4251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->inner_method); 4261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_EAP_AUTH_CRED_TYPE: 4281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < 1) 4291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->cred_type = *pos; 4311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Credential Type: %u", 4321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->cred_type); 4331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_EAP_AUTH_TUNNELED_CRED_TYPE: 4351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < 1) 4361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->tunneled_cred_type = *pos; 4381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Tunneled EAP Method Credential " 4391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Type: %u", e->tunneled_cred_type); 4401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt default: 4421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Unsupported Authentication " 4431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Parameter: id=%u len=%u", id, len); 4441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump(MSG_DEBUG, "Authentication Parameter " 4451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Value", pos, len); 4461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += len; 4501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return e_end; 4531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 4541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic const u8 * nai_realm_parse_realm(struct nai_realm *r, const u8 *pos, 4571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *end) 4581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 4591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 len; 4601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *f_end; 4611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 realm_len, e; 4621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (end - pos < 4) { 4641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for NAI Realm Data " 4651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "fixed fields"); 4661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = WPA_GET_LE16(pos); /* NAI Realm Data field Length */ 4701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 471d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (len > end - pos || len < 3) { 4721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for NAI Realm Data " 4731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "(len=%u; left=%u)", 4741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len, (unsigned int) (end - pos)); 4751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt f_end = pos + len; 4781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt r->encoding = *pos++; 4801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt realm_len = *pos++; 481d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (realm_len > f_end - pos) { 4821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for NAI Realm " 4831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "(len=%u; left=%u)", 4841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt realm_len, (unsigned int) (f_end - pos)); 4851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "NAI Realm", pos, realm_len); 4884b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt r->realm = dup_binstr(pos, realm_len); 4891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (r->realm == NULL) 4901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += realm_len; 4921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 493d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (f_end - pos < 1) { 4941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for EAP Method Count"); 4951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt r->eap_count = *pos++; 4981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP Count: %u", r->eap_count); 499d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (r->eap_count * 3 > f_end - pos) { 5001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for EAP Methods"); 5011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 5021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 50361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt r->eap = os_calloc(r->eap_count, sizeof(struct nai_realm_eap)); 5041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (r->eap == NULL) 5051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 5061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (e = 0; e < r->eap_count; e++) { 5081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = nai_realm_parse_eap(&r->eap[e], pos, f_end); 5091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos == NULL) 5101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 5111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return f_end; 5141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 5151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct nai_realm * nai_realm_parse(struct wpabuf *anqp, u16 *count) 5181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 5191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm *realm; 5201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *pos, *end; 5211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 i, num; 5226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t left; 5231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (anqp == NULL) 5256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 5266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt left = wpabuf_len(anqp); 5276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (left < 2) 5281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 5291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = wpabuf_head_u8(anqp); 5316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt end = pos + left; 5321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt num = WPA_GET_LE16(pos); 5331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "NAI Realm Count: %u", num); 5341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 5356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt left -= 2; 5361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (num > left / 5) { 5381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid NAI Realm Count %u - not " 5391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "enough data (%u octets) for that many realms", 5406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt num, (unsigned int) left); 5411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 5421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 54461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt realm = os_calloc(num, sizeof(struct nai_realm)); 5451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (realm == NULL) 5461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 5471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < num; i++) { 5491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = nai_realm_parse_realm(&realm[i], pos, end); 5501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos == NULL) { 5511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, num); 5521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 5531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *count = num; 5571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return realm; 5581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 5591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int nai_realm_match(struct nai_realm *realm, const char *home_realm) 5621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 5631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt char *tmp, *pos, *end; 5641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int match = 0; 5651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (realm->realm == NULL || home_realm == NULL) 5671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 5681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_strchr(realm->realm, ';') == NULL) 5701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return os_strcasecmp(realm->realm, home_realm) == 0; 5711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt tmp = os_strdup(realm->realm); 5731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (tmp == NULL) 5741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 5751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = tmp; 5771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (*pos) { 5781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = os_strchr(pos, ';'); 5791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (end) 5801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *end = '\0'; 5811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_strcasecmp(pos, home_realm) == 0) { 5821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt match = 1; 5831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 5841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (end == NULL) 5861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 5871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = end + 1; 5881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(tmp); 5911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return match; 5931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 5941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 596807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtstatic int nai_realm_cred_username(struct wpa_supplicant *wpa_s, 597807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt struct nai_realm_eap *eap) 5981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 599807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (eap_get_name(EAP_VENDOR_IETF, eap->method) == NULL) { 600807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 601807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt "nai-realm-cred-username: EAP method not supported: %d", 602807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt eap->method); 6031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; /* method not supported */ 604807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } 6051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 606fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (eap->method != EAP_TYPE_TTLS && eap->method != EAP_TYPE_PEAP && 607fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt eap->method != EAP_TYPE_FAST) { 6081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Only tunneled methods with username/password supported */ 609807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 610807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt "nai-realm-cred-username: Method: %d is not TTLS, PEAP, or FAST", 611807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt eap->method); 6121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 6131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 615fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (eap->method == EAP_TYPE_PEAP || eap->method == EAP_TYPE_FAST) { 616a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (eap->inner_method && 617807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL) { 618807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 619807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt "nai-realm-cred-username: PEAP/FAST: Inner method not supported: %d", 620807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt eap->inner_method); 621a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 0; 622807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } 623a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (!eap->inner_method && 624807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt eap_get_name(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2) == NULL) { 625807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 626807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt "nai-realm-cred-username: MSCHAPv2 not supported"); 627a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 0; 628807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } 629a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 6301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->method == EAP_TYPE_TTLS) { 6321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->inner_method == 0 && eap->inner_non_eap == 0) 633a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 1; /* Assume TTLS/MSCHAPv2 is used */ 6341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->inner_method && 635807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL) { 636807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 637807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt "nai-realm-cred-username: TTLS, but inner not supported: %d", 638807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt eap->inner_method); 6391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 640807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } 6411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->inner_non_eap && 6421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_PAP && 6431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_CHAP && 6441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_MSCHAP && 645807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_MSCHAPV2) { 646807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 647807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt "nai-realm-cred-username: TTLS, inner-non-eap not supported: %d", 648807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt eap->inner_non_eap); 6491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 650807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } 6511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->inner_method && 6541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_method != EAP_TYPE_GTC && 655807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt eap->inner_method != EAP_TYPE_MSCHAPV2) { 656807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 657807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt "nai-realm-cred-username: inner-method not GTC or MSCHAPv2: %d", 658807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt eap->inner_method); 6591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 660807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } 6611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 1; 6631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 6641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 666807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtstatic int nai_realm_cred_cert(struct wpa_supplicant *wpa_s, 667807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt struct nai_realm_eap *eap) 66804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 669807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (eap_get_name(EAP_VENDOR_IETF, eap->method) == NULL) { 670807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 671807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt "nai-realm-cred-cert: Method not supported: %d", 672807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt eap->method); 67304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; /* method not supported */ 674807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } 67504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 67604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (eap->method != EAP_TYPE_TLS) { 67704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Only EAP-TLS supported for credential authentication */ 678807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 679807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt "nai-realm-cred-cert: Method not TLS: %d", 680807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt eap->method); 68104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 68204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 68304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 68404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 1; 68504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 68604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 68704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 688807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtstatic struct nai_realm_eap * nai_realm_find_eap(struct wpa_supplicant *wpa_s, 689807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt struct wpa_cred *cred, 6901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm *realm) 6911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 6921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 e; 6931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 694807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (cred->username == NULL || 69504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->username[0] == '\0' || 69604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ((cred->password == NULL || 69704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->password[0] == '\0') && 69804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (cred->private_key == NULL || 699807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt cred->private_key[0] == '\0'))) { 700807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 701807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt "nai-realm-find-eap: incomplete cred info: username: %s password: %s private_key: %s", 702807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt cred->username ? cred->username : "NULL", 703807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt cred->password ? cred->password : "NULL", 704807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt cred->private_key ? cred->private_key : "NULL"); 7051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 706807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } 7071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (e = 0; e < realm->eap_count; e++) { 7091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm_eap *eap = &realm->eap[e]; 71004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->password && cred->password[0] && 711807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt nai_realm_cred_username(wpa_s, eap)) 71204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return eap; 71304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->private_key && cred->private_key[0] && 714807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt nai_realm_cred_cert(wpa_s, eap)) 7151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eap; 7161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 7191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 7201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef INTERWORKING_3GPP 7231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int plmn_id_match(struct wpabuf *anqp, const char *imsi, int mnc_len) 7251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 72634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 plmn[3], plmn2[3]; 7271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *pos, *end; 7281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 udhl; 7291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 73034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* 73134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * See Annex A of 3GPP TS 24.234 v8.1.0 for description. The network 73234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * operator is allowed to include only two digits of the MNC, so allow 73334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * matches based on both two and three digit MNC assumptions. Since some 73434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * SIM/USIM cards may not expose MNC length conveniently, we may be 73534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * provided the default MNC length 3 here and as such, checking with MNC 73634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * length 2 is justifiable even though 3GPP TS 24.234 does not mention 73734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * that case. Anyway, MCC/MNC pair where both 2 and 3 digit MNC is used 73834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * with otherwise matching values would not be good idea in general, so 73934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * this should not result in selecting incorrect networks. 74034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt */ 74134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* Match with 3 digit MNC */ 7421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt plmn[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4); 74334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt plmn[1] = (imsi[2] - '0') | ((imsi[5] - '0') << 4); 7441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt plmn[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4); 74534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* Match with 2 digit MNC */ 74634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt plmn2[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4); 74734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt plmn2[1] = (imsi[2] - '0') | 0xf0; 74834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt plmn2[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4); 7491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (anqp == NULL) 7511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 7521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = wpabuf_head_u8(anqp); 7531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = pos + wpabuf_len(anqp); 754d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (end - pos < 2) 7551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 7561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (*pos != 0) { 7571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Unsupported GUD version 0x%x", *pos); 7581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 7591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos++; 7611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt udhl = *pos++; 762d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (udhl > end - pos) { 7631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid UDHL"); 7641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 7651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = pos + udhl; 7671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 76834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Matching against MCC/MNC alternatives: %02x:%02x:%02x or %02x:%02x:%02x (IMSI %s, MNC length %d)", 76934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt plmn[0], plmn[1], plmn[2], plmn2[0], plmn2[1], plmn2[2], 77034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt imsi, mnc_len); 77134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 772d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt while (end - pos >= 2) { 7731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 iei, len; 7741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *l_end; 7751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iei = *pos++; 7761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = *pos++ & 0x7f; 777d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (len > end - pos) 7781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 7791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt l_end = pos + len; 7801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (iei == 0 && len > 0) { 7821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* PLMN List */ 7831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 num, i; 78434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "Interworking: PLMN List information element", 78534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos, len); 7861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt num = *pos++; 7871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < num; i++) { 788d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (l_end - pos < 3) 7891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 79034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (os_memcmp(pos, plmn, 3) == 0 || 79134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcmp(pos, plmn2, 3) == 0) 7921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 1; /* Found matching PLMN */ 79361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += 3; 7941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 79534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } else { 79634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "Interworking: Unrecognized 3GPP information element", 79734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos, len); 7981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = l_end; 8011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 8021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 8041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 8051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 80704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int build_root_nai(char *nai, size_t nai_len, const char *imsi, 80861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t mnc_len, char prefix) 8091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 8101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const char *sep, *msin; 81104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char *end, *pos; 8121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t msin_len, plmn_len; 8131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 8151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * TS 23.003, Clause 14 (3GPP to WLAN Interworking) 8161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Root NAI: 8171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * <aka:0|sim:1><IMSI>@wlan.mnc<MNC>.mcc<MCC>.3gppnetwork.org 8181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * <MNC> is zero-padded to three digits in case two-digit MNC is used 8191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 8201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (imsi == NULL || os_strlen(imsi) > 16) { 8221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No valid IMSI available"); 8231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 8241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 8251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sep = os_strchr(imsi, '-'); 82661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sep) { 82761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt plmn_len = sep - imsi; 82861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt msin = sep + 1; 82961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else if (mnc_len && os_strlen(imsi) >= 3 + mnc_len) { 83061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt plmn_len = 3 + mnc_len; 83161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt msin = imsi + plmn_len; 83261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else 8331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 8341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (plmn_len != 5 && plmn_len != 6) 8351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 8361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt msin_len = os_strlen(msin); 8371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = nai; 83904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt end = nai + nai_len; 84004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (prefix) 84104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *pos++ = prefix; 8421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(pos, imsi, plmn_len); 8431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += plmn_len; 8441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(pos, msin, msin_len); 8451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += msin_len; 8461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += os_snprintf(pos, end - pos, "@wlan.mnc"); 8471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (plmn_len == 5) { 8481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = '0'; 8491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = imsi[3]; 8501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = imsi[4]; 8511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 8521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = imsi[3]; 8531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = imsi[4]; 8541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = imsi[5]; 8551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 856c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_snprintf(pos, end - pos, ".mcc%c%c%c.3gppnetwork.org", 857c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt imsi[0], imsi[1], imsi[2]); 8581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 85904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 86004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 86104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 86204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 86304949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int set_root_nai(struct wpa_ssid *ssid, const char *imsi, char prefix) 86404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 86504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char nai[100]; 86661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (build_root_nai(nai, sizeof(nai), imsi, 0, prefix) < 0) 86704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 8681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return wpa_config_set_quoted(ssid, "identity", nai); 8691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 8701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* INTERWORKING_3GPP */ 8721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8745460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidtstatic int already_connected(struct wpa_supplicant *wpa_s, 8755460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt struct wpa_cred *cred, struct wpa_bss *bss) 8765460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt{ 8774582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt struct wpa_ssid *ssid, *sel_ssid; 8784582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt struct wpa_bss *selected; 8795460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8805460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (wpa_s->wpa_state < WPA_ASSOCIATED || wpa_s->current_ssid == NULL) 8815460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return 0; 8825460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8835460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt ssid = wpa_s->current_ssid; 8845460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (ssid->parent_cred != cred) 8855460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return 0; 8865460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8875460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (ssid->ssid_len != bss->ssid_len || 8885460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) != 0) 8895460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return 0; 8905460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8914582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt sel_ssid = NULL; 8924582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt selected = wpa_supplicant_pick_network(wpa_s, &sel_ssid); 8934582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt if (selected && sel_ssid && sel_ssid->priority > ssid->priority) 8944582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt return 0; /* higher priority network in scan results */ 8954582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt 8965460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return 1; 8975460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt} 8985460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8995460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 9005460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidtstatic void remove_duplicate_network(struct wpa_supplicant *wpa_s, 9015460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt struct wpa_cred *cred, 9025460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt struct wpa_bss *bss) 9035460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt{ 9045460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt struct wpa_ssid *ssid; 9055460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 9065460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 9075460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (ssid->parent_cred != cred) 9085460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt continue; 9095460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (ssid->ssid_len != bss->ssid_len || 9105460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) != 0) 9115460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt continue; 9125460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 9135460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt break; 9145460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt } 9155460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 9165460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (ssid == NULL) 9175460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return; 9185460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 9195460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Remove duplicate network entry for the same credential"); 9205460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 9215460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (ssid == wpa_s->current_ssid) { 9225460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_sm_set_config(wpa_s->wpa, NULL); 9235460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 924203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt wpa_s->own_disconnect_req = 1; 9255460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_supplicant_deauthenticate(wpa_s, 9265460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt WLAN_REASON_DEAUTH_LEAVING); 9275460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt } 9285460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 9295460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpas_notify_network_removed(wpa_s, ssid); 9305460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_config_remove_network(wpa_s->conf, ssid->id); 9315460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt} 9325460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 9335460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 934d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic int interworking_set_hs20_params(struct wpa_supplicant *wpa_s, 935d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpa_ssid *ssid) 93661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 9375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt const char *key_mgmt = NULL; 9385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#ifdef CONFIG_IEEE80211R 9395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt int res; 9405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt struct wpa_driver_capa capa; 9415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 9425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt res = wpa_drv_get_capa(wpa_s, &capa); 9435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (res == 0 && capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) { 9445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt key_mgmt = wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ? 9455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt "WPA-EAP WPA-EAP-SHA256 FT-EAP" : 9465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt "WPA-EAP FT-EAP"; 9475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 9485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#endif /* CONFIG_IEEE80211R */ 9495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 9505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (!key_mgmt) 9515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt key_mgmt = wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ? 9525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt "WPA-EAP WPA-EAP-SHA256" : "WPA-EAP"; 95358d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0 || 95458d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt wpa_config_set(ssid, "proto", "RSN", 0) < 0 || 95558d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0) 95661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 95761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 95861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 95961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 96061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 9611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int interworking_connect_3gpp(struct wpa_supplicant *wpa_s, 962f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpa_cred *cred, 9637f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt struct wpa_bss *bss, int only_add) 9641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 9651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef INTERWORKING_3GPP 9661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_ssid *ssid; 9674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int eap_type; 9684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int res; 9694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt char prefix; 9701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 9714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL) 97204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 97304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 974216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Connect with " MACSTR 975216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt " (3GPP)", MAC2STR(bss->bssid)); 9761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 9775460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (already_connected(wpa_s, cred, bss)) { 9785460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR, 9795460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt MAC2STR(bss->bssid)); 9807f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return wpa_s->current_ssid->id; 9815460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt } 9825460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 9835460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt remove_duplicate_network(wpa_s, cred, bss); 9845460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 9851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid = wpa_config_add_network(wpa_s->conf); 9861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ssid == NULL) 9871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 988d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt ssid->parent_cred = cred; 9891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 9901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpas_notify_network_added(wpa_s, ssid); 9911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_config_set_network_defaults(ssid); 99204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ssid->priority = cred->priority; 9931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid->temporary = 1; 9945460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt ssid->ssid = os_zalloc(bss->ssid_len + 1); 9951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ssid->ssid == NULL) 9961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 9975460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len); 9985460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt ssid->ssid_len = bss->ssid_len; 999f9bdef99ce3b2858f2812c745a3d6bb093fb0e5dDmitry Shmidt ssid->eap.sim_num = cred->sim_num; 10001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1001d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (interworking_set_hs20_params(wpa_s, ssid) < 0) 100261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto fail; 100361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 10044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_type = EAP_TYPE_SIM; 10054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->pcsc && wpa_s->scard && scard_supports_umts(wpa_s->scard)) 10064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_type = EAP_TYPE_AKA; 10074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->eap_method && cred->eap_method[0].vendor == EAP_VENDOR_IETF) { 10084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->eap_method[0].method == EAP_TYPE_SIM || 10094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt cred->eap_method[0].method == EAP_TYPE_AKA || 10104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt cred->eap_method[0].method == EAP_TYPE_AKA_PRIME) 10114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_type = cred->eap_method[0].method; 10124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 10134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 10144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt switch (eap_type) { 10154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case EAP_TYPE_SIM: 10164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt prefix = '1'; 10174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt res = wpa_config_set(ssid, "eap", "SIM", 0); 10184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt break; 10194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case EAP_TYPE_AKA: 10204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt prefix = '0'; 10214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt res = wpa_config_set(ssid, "eap", "AKA", 0); 10224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt break; 10234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case EAP_TYPE_AKA_PRIME: 10244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt prefix = '6'; 10254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt res = wpa_config_set(ssid, "eap", "AKA'", 0); 10264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt break; 10274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt default: 10284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt res = -1; 10294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt break; 10304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 10314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (res < 0) { 1032216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1033216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Selected EAP method (%d) not supported", eap_type); 10341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 10351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 10364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 10374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!cred->pcsc && set_root_nai(ssid, cred->imsi, prefix) < 0) { 1038216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, "Failed to set Root NAI"); 10391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 10401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 10411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 104204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->milenage && cred->milenage[0]) { 10431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set_quoted(ssid, "password", 104404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->milenage) < 0) 10451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 104604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else if (cred->pcsc) { 10471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set_quoted(ssid, "pcsc", "") < 0) 10481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 104904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->conf->pcsc_pin && 105004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_config_set_quoted(ssid, "pin", wpa_s->conf->pcsc_pin) 105104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt < 0) 105204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto fail; 10531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 10541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1055f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->next_ssid = ssid; 105604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_config_update_prio_list(wpa_s->conf); 10577f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (!only_add) 10587f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt interworking_reconnect(wpa_s); 10591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10607f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return ssid->id; 10611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtfail: 10631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpas_notify_network_removed(wpa_s, ssid); 10641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_config_remove_network(wpa_s->conf, ssid->id); 10651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* INTERWORKING_3GPP */ 10661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 10671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 10681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 107061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int roaming_consortium_element_match(const u8 *ie, const u8 *rc_id, 107161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t rc_len) 107261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 107361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *pos, *end; 107461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 lens; 107561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 107661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ie == NULL) 107761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 107861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 107961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = ie + 2; 108061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt end = ie + 2 + ie[1]; 108161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 108261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Roaming Consortium element: 108361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Number of ANQP OIs 108461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * OI #1 and #2 lengths 108561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * OI #1, [OI #2], [OI #3] 108661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 108761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1088d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (end - pos < 2) 108961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 109061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 109161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos++; /* skip Number of ANQP OIs */ 109261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt lens = *pos++; 1093d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if ((lens & 0x0f) + (lens >> 4) > end - pos) 109461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 109561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 109661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if ((lens & 0x0f) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0) 109761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 1; 109861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += lens & 0x0f; 109961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 110061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if ((lens >> 4) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0) 110161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 1; 110261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += lens >> 4; 110361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 110461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos < end && (size_t) (end - pos) == rc_len && 110561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcmp(pos, rc_id, rc_len) == 0) 110661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 1; 110761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 110861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 110961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 111061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 111161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 111261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int roaming_consortium_anqp_match(const struct wpabuf *anqp, 111361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *rc_id, size_t rc_len) 111461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 111561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *pos, *end; 111661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 len; 111761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 111861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (anqp == NULL) 111961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 112061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 112161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = wpabuf_head(anqp); 112261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt end = pos + wpabuf_len(anqp); 112361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 112461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Set of <OI Length, OI> duples */ 112561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt while (pos < end) { 112661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len = *pos++; 1127d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (len > end - pos) 112861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 112961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (len == rc_len && os_memcmp(pos, rc_id, rc_len) == 0) 113061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 1; 113161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += len; 113261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 113361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 113461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 113561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 113661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 113761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 113861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int roaming_consortium_match(const u8 *ie, const struct wpabuf *anqp, 113961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *rc_id, size_t rc_len) 114061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 114161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return roaming_consortium_element_match(ie, rc_id, rc_len) || 114261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt roaming_consortium_anqp_match(anqp, rc_id, rc_len); 114361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 114461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 114561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1146051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic int cred_no_required_oi_match(struct wpa_cred *cred, struct wpa_bss *bss) 1147051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 1148051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt const u8 *ie; 1149051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1150051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (cred->required_roaming_consortium_len == 0) 1151051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 1152051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1153051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM); 1154051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1155051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (ie == NULL && 1156051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL)) 1157051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 1; 1158051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1159051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return !roaming_consortium_match(ie, 1160051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt bss->anqp ? 1161051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt bss->anqp->roaming_consortium : NULL, 1162051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt cred->required_roaming_consortium, 1163051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt cred->required_roaming_consortium_len); 1164051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 1165051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1166051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1167a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic int cred_excluded_ssid(struct wpa_cred *cred, struct wpa_bss *bss) 1168a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{ 1169a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt size_t i; 1170a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1171a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (!cred->excluded_ssid) 1172a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 0; 1173a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1174a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt for (i = 0; i < cred->num_excluded_ssid; i++) { 1175a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt struct excluded_ssid *e = &cred->excluded_ssid[i]; 1176a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (bss->ssid_len == e->ssid_len && 1177a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_memcmp(bss->ssid, e->ssid, e->ssid_len) == 0) 1178a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 1; 1179a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1180a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1181a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 0; 1182a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt} 1183a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1184a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1185f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int cred_below_min_backhaul(struct wpa_supplicant *wpa_s, 1186f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred, struct wpa_bss *bss) 1187f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 1188d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef CONFIG_HS20 1189f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int res; 1190f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt unsigned int dl_bandwidth, ul_bandwidth; 1191f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt const u8 *wan; 1192f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u8 wan_info, dl_load, ul_load; 1193f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u16 lmd; 1194f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u32 ul_speed, dl_speed; 1195f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1196f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!cred->min_dl_bandwidth_home && 1197f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt !cred->min_ul_bandwidth_home && 1198f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt !cred->min_dl_bandwidth_roaming && 1199f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt !cred->min_ul_bandwidth_roaming) 1200f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* No bandwidth constraint specified */ 1201f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1202f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (bss->anqp == NULL || bss->anqp->hs20_wan_metrics == NULL) 1203f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* No WAN Metrics known - ignore constraint */ 1204f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1205f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wan = wpabuf_head(bss->anqp->hs20_wan_metrics); 1206f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wan_info = wan[0]; 1207f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (wan_info & BIT(3)) 1208f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; /* WAN link at capacity */ 1209f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt lmd = WPA_GET_LE16(wan + 11); 1210f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (lmd == 0) 1211f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* Downlink/Uplink Load was not measured */ 1212f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt dl_speed = WPA_GET_LE32(wan + 1); 1213f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ul_speed = WPA_GET_LE32(wan + 5); 1214f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt dl_load = wan[9]; 1215f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ul_load = wan[10]; 1216f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1217f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (dl_speed >= 0xffffff) 1218f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt dl_bandwidth = dl_speed / 255 * (255 - dl_load); 1219f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt else 1220f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt dl_bandwidth = dl_speed * (255 - dl_load) / 255; 1221f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1222f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (ul_speed >= 0xffffff) 1223f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ul_bandwidth = ul_speed / 255 * (255 - ul_load); 1224f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt else 1225f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ul_bandwidth = ul_speed * (255 - ul_load) / 255; 1226f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1227f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt res = interworking_home_sp_cred(wpa_s, cred, bss->anqp ? 1228f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bss->anqp->domain_name : NULL); 1229f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (res > 0) { 1230f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred->min_dl_bandwidth_home > dl_bandwidth) 1231f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 1232f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred->min_ul_bandwidth_home > ul_bandwidth) 1233f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 1234f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 1235f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred->min_dl_bandwidth_roaming > dl_bandwidth) 1236f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 1237f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred->min_ul_bandwidth_roaming > ul_bandwidth) 1238f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 1239f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1240d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* CONFIG_HS20 */ 1241f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1242f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; 1243f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 1244f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1245f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1246f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int cred_over_max_bss_load(struct wpa_supplicant *wpa_s, 1247f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred, struct wpa_bss *bss) 1248f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 1249f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt const u8 *ie; 1250f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int res; 1251f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1252f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!cred->max_bss_load) 1253f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* No BSS Load constraint specified */ 1254f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1255f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_BSS_LOAD); 1256f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (ie == NULL || ie[1] < 3) 1257f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* No BSS Load advertised */ 1258f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1259f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt res = interworking_home_sp_cred(wpa_s, cred, bss->anqp ? 1260f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bss->anqp->domain_name : NULL); 1261f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (res <= 0) 1262f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* Not a home network */ 1263f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1264f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return ie[4] > cred->max_bss_load; 1265f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 1266f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1267f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1268d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef CONFIG_HS20 1269d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1270f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int has_proto_match(const u8 *pos, const u8 *end, u8 proto) 1271f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 1272d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt while (end - pos >= 4) { 1273f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (pos[0] == proto && pos[3] == 1 /* Open */) 1274f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 1275f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt pos += 4; 1276f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1277f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1278f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; 1279f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 1280f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1281f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1282f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int has_proto_port_match(const u8 *pos, const u8 *end, u8 proto, 1283f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u16 port) 1284f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 1285d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt while (end - pos >= 4) { 1286f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (pos[0] == proto && WPA_GET_LE16(&pos[1]) == port && 1287f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt pos[3] == 1 /* Open */) 1288f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 1289f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt pos += 4; 1290f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1291f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1292f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; 1293f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 1294f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1295d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* CONFIG_HS20 */ 1296d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1297f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1298f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int cred_conn_capab_missing(struct wpa_supplicant *wpa_s, 1299f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred, struct wpa_bss *bss) 1300f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 1301d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef CONFIG_HS20 1302f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int res; 1303f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt const u8 *capab, *end; 1304f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt unsigned int i, j; 1305f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int *ports; 1306f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1307f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!cred->num_req_conn_capab) 1308f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* No connection capability constraint specified */ 1309f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1310f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (bss->anqp == NULL || bss->anqp->hs20_connection_capability == NULL) 1311f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* No Connection Capability known - ignore constraint 1312f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt */ 1313f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1314f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt res = interworking_home_sp_cred(wpa_s, cred, bss->anqp ? 1315f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bss->anqp->domain_name : NULL); 1316f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (res > 0) 1317f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* No constraint in home network */ 1318f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1319f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt capab = wpabuf_head(bss->anqp->hs20_connection_capability); 1320f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt end = capab + wpabuf_len(bss->anqp->hs20_connection_capability); 1321f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1322f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (i = 0; i < cred->num_req_conn_capab; i++) { 1323f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ports = cred->req_conn_capab_port[i]; 1324f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ports) { 1325f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!has_proto_match(capab, end, 1326f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->req_conn_capab_proto[i])) 1327f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 1328f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 1329f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (j = 0; ports[j] > -1; j++) { 1330f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!has_proto_port_match( 1331f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt capab, end, 1332f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->req_conn_capab_proto[i], 1333f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ports[j])) 1334f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 1335f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1336f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1337f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1338d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* CONFIG_HS20 */ 1339f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1340f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; 1341f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 1342f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1343f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 134461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic struct wpa_cred * interworking_credentials_available_roaming_consortium( 1345f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 1346f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int *excluded) 134761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 134861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_cred *cred, *selected = NULL; 134961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *ie; 1350f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int is_excluded = 0; 135161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 135261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM); 135361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 13544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ie == NULL && 13554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL)) 135661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return NULL; 135761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 135861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_s->conf->cred == NULL) 135961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return NULL; 136061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 136161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 136261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->roaming_consortium_len == 0) 136361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt continue; 136461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 13654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!roaming_consortium_match(ie, 13664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss->anqp ? 13674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss->anqp->roaming_consortium : 13684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt NULL, 136961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->roaming_consortium, 137061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->roaming_consortium_len)) 137161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt continue; 137261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1373051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (cred_no_required_oi_match(cred, bss)) 1374051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt continue; 1375f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && cred_below_min_backhaul(wpa_s, cred, bss)) 1376f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1377f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && cred_over_max_bss_load(wpa_s, cred, bss)) 1378f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1379f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && cred_conn_capab_missing(wpa_s, cred, bss)) 1380f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1381f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred_excluded_ssid(cred, bss)) { 1382f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded == NULL) 1383f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1384f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected == NULL) { 1385f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = cred; 1386f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt is_excluded = 1; 1387f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1388f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 1389f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected == NULL || is_excluded || 1390f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_prio_cmp(selected, cred) < 0) { 1391f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = cred; 1392f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt is_excluded = 0; 1393f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1394f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 139561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 139661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1397f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded) 1398f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt *excluded = is_excluded; 1399f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 140061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return selected; 140161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 140261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 140361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 140461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int interworking_set_eap_params(struct wpa_ssid *ssid, 140561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_cred *cred, int ttls) 140661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 140761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->eap_method) { 140861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ttls = cred->eap_method->vendor == EAP_VENDOR_IETF && 140961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->eap_method->method == EAP_TYPE_TTLS; 141061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 141161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(ssid->eap.eap_methods); 141261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->eap.eap_methods = 141361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_malloc(sizeof(struct eap_method_type) * 2); 141461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ssid->eap.eap_methods == NULL) 141561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 141661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(ssid->eap.eap_methods, cred->eap_method, 141761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sizeof(*cred->eap_method)); 141861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->eap.eap_methods[1].vendor = EAP_VENDOR_IETF; 141961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->eap.eap_methods[1].method = EAP_TYPE_NONE; 142061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 142161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 142261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ttls && cred->username && cred->username[0]) { 142361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const char *pos; 142461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt char *anon; 142561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Use anonymous NAI in Phase 1 */ 142661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = os_strchr(cred->username, '@'); 142761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos) { 142861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t buflen = 9 + os_strlen(pos) + 1; 142961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anon = os_malloc(buflen); 143061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (anon == NULL) 143161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 143261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_snprintf(anon, buflen, "anonymous%s", pos); 143361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else if (cred->realm) { 143461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t buflen = 10 + os_strlen(cred->realm) + 1; 143561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anon = os_malloc(buflen); 143661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (anon == NULL) 143761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 143861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_snprintf(anon, buflen, "anonymous@%s", cred->realm); 143961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else { 144061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anon = os_strdup("anonymous"); 144161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (anon == NULL) 144261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 144361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 144461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_config_set_quoted(ssid, "anonymous_identity", anon) < 144561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 0) { 144661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(anon); 144761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 144861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 144961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(anon); 145061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 145161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1452e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (!ttls && cred->username && cred->username[0] && cred->realm && 1453e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt !os_strchr(cred->username, '@')) { 1454e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt char *id; 1455e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt size_t buflen; 1456e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt int res; 1457e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 1458e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt buflen = os_strlen(cred->username) + 1 + 1459e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt os_strlen(cred->realm) + 1; 1460e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 1461e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt id = os_malloc(buflen); 1462e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (!id) 1463e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt return -1; 1464e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt os_snprintf(id, buflen, "%s@%s", cred->username, cred->realm); 1465e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt res = wpa_config_set_quoted(ssid, "identity", id); 1466e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt os_free(id); 1467e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (res < 0) 1468e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt return -1; 1469e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt } else if (cred->username && cred->username[0] && 147061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "identity", cred->username) < 0) 147161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 147261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 147361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->password && cred->password[0]) { 147461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->ext_password && 147561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set(ssid, "password", cred->password, 0) < 0) 147661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 147761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!cred->ext_password && 147861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "password", cred->password) < 147961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 0) 148061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 148161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 148261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 148361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->client_cert && cred->client_cert[0] && 148461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "client_cert", cred->client_cert) < 0) 148561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 148661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1487d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#ifdef ANDROID 1488d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (cred->private_key && 1489d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt os_strncmp(cred->private_key, "keystore://", 11) == 0) { 1490d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt /* Use OpenSSL engine configuration for Android keystore */ 1491d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (wpa_config_set_quoted(ssid, "engine_id", "keystore") < 0 || 1492d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_config_set_quoted(ssid, "key_id", 1493d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt cred->private_key + 11) < 0 || 1494d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_config_set(ssid, "engine", "1", 0) < 0) 1495d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return -1; 1496d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } else 1497d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#endif /* ANDROID */ 149861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->private_key && cred->private_key[0] && 149961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "private_key", cred->private_key) < 0) 150061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 150161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 150261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->private_key_passwd && cred->private_key_passwd[0] && 150361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "private_key_passwd", 150461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->private_key_passwd) < 0) 150561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 150661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 150761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->phase1) { 150861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(ssid->eap.phase1); 150961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->eap.phase1 = os_strdup(cred->phase1); 151061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 151161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->phase2) { 151261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(ssid->eap.phase2); 151361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->eap.phase2 = os_strdup(cred->phase2); 151461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 151561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 151661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->ca_cert && cred->ca_cert[0] && 151761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "ca_cert", cred->ca_cert) < 0) 151861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 151961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1520051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (cred->domain_suffix_match && cred->domain_suffix_match[0] && 1521051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_config_set_quoted(ssid, "domain_suffix_match", 1522051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt cred->domain_suffix_match) < 0) 1523051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return -1; 1524051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1525f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ssid->eap.ocsp = cred->ocsp; 1526f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 152761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 152861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 152961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 153061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 153161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int interworking_connect_roaming_consortium( 153261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_cred *cred, 15337f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt struct wpa_bss *bss, int only_add) 153461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 153561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_ssid *ssid; 153661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1537216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Connect with " MACSTR 1538216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt " based on roaming consortium match", MAC2STR(bss->bssid)); 153961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 15405460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (already_connected(wpa_s, cred, bss)) { 15415460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR, 15425460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt MAC2STR(bss->bssid)); 15437f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return wpa_s->current_ssid->id; 15445460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt } 15455460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 15465460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt remove_duplicate_network(wpa_s, cred, bss); 15475460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 154861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid = wpa_config_add_network(wpa_s->conf); 154961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ssid == NULL) 155061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 1551d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt ssid->parent_cred = cred; 155261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpas_notify_network_added(wpa_s, ssid); 155361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_network_defaults(ssid); 155461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->priority = cred->priority; 155561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->temporary = 1; 15565460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt ssid->ssid = os_zalloc(bss->ssid_len + 1); 155761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ssid->ssid == NULL) 155861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto fail; 15595460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len); 15605460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt ssid->ssid_len = bss->ssid_len; 156161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1562d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (interworking_set_hs20_params(wpa_s, ssid) < 0) 156361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto fail; 156461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 156561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->eap_method == NULL) { 1566216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1567216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: No EAP method set for credential using roaming consortium"); 156861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto fail; 156961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 157061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 157161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (interworking_set_eap_params( 157261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid, cred, 157361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->eap_method->vendor == EAP_VENDOR_IETF && 157461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->eap_method->method == EAP_TYPE_TTLS) < 0) 157561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto fail; 157661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1577f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->next_ssid = ssid; 157861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_update_prio_list(wpa_s->conf); 15797f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (!only_add) 15807f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt interworking_reconnect(wpa_s); 158161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 15827f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return ssid->id; 158361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 158461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtfail: 158561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpas_notify_network_removed(wpa_s, ssid); 158661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_remove_network(wpa_s->conf, ssid->id); 158761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 158861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 158961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 159061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 159158d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidtint interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, 159258d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt int only_add) 15931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1594f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpa_cred *cred, *cred_rc, *cred_3gpp; 15951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_ssid *ssid; 15961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm *realm; 15971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm_eap *eap = NULL; 15981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 count, i; 15991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt char buf[100]; 160058d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt int excluded = 0, *excl = &excluded; 160109f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt const char *name; 16021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 160304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->conf->cred == NULL || bss == NULL) 16041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 16055460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (disallowed_bssid(wpa_s, bss->bssid) || 16065460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) { 1607216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1608216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Reject connection to disallowed BSS " 1609216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 16101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 16111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 16121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1613f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Considering BSS " MACSTR 161458d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt " for connection", 161558d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt MAC2STR(bss->bssid)); 1616f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 161761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) { 161861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 161961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * We currently support only HS 2.0 networks and those are 162061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * required to use WPA2-Enterprise. 162161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 1622216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1623216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Network does not use RSN"); 162461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 162561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 162661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1627f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_rc = interworking_credentials_available_roaming_consortium( 1628f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s, bss, 0, excl); 1629f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (cred_rc) { 1630216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1631216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Highest roaming consortium matching credential priority %d sp_priority %d", 1632216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt cred_rc->priority, cred_rc->sp_priority); 163358d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt if (excl && !(*excl)) 1634f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excl = NULL; 1635f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1636f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1637f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred = interworking_credentials_available_realm(wpa_s, bss, 0, excl); 1638f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (cred) { 1639216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1640216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Highest NAI Realm list matching credential priority %d sp_priority %d", 1641216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt cred->priority, cred->sp_priority); 164258d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt if (excl && !(*excl)) 1643f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excl = NULL; 1644f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1645f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1646f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_3gpp = interworking_credentials_available_3gpp(wpa_s, bss, 0, 1647f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excl); 1648f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (cred_3gpp) { 1649216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1650216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Highest 3GPP matching credential priority %d sp_priority %d", 1651216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt cred_3gpp->priority, cred_3gpp->sp_priority); 165258d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt if (excl && !(*excl)) 1653f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excl = NULL; 1654f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1655f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1656f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!cred_rc && !cred && !cred_3gpp) { 1657216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1658216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: No full credential matches - consider options without BW(etc.) limits"); 1659f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_rc = interworking_credentials_available_roaming_consortium( 1660f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s, bss, 1, excl); 1661f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred_rc) { 1662216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1663216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Highest roaming consortium matching credential priority %d sp_priority %d (ignore BW)", 1664216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt cred_rc->priority, cred_rc->sp_priority); 166558d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt if (excl && !(*excl)) 1666f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excl = NULL; 1667f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1668f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1669f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred = interworking_credentials_available_realm(wpa_s, bss, 1, 1670f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excl); 1671f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred) { 1672216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1673216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Highest NAI Realm list matching credential priority %d sp_priority %d (ignore BW)", 1674216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt cred->priority, cred->sp_priority); 167558d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt if (excl && !(*excl)) 1676f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excl = NULL; 1677f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1678f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1679f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_3gpp = interworking_credentials_available_3gpp(wpa_s, bss, 1680f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1, excl); 1681f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred_3gpp) { 1682216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1683216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Highest 3GPP matching credential priority %d sp_priority %d (ignore BW)", 1684216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt cred_3gpp->priority, cred_3gpp->sp_priority); 168558d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt if (excl && !(*excl)) 1686f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excl = NULL; 1687f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1688f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1689f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1690f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (cred_rc && 1691f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (cred == NULL || cred_prio_cmp(cred_rc, cred) >= 0) && 1692f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (cred_3gpp == NULL || cred_prio_cmp(cred_rc, cred_3gpp) >= 0)) 1693f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return interworking_connect_roaming_consortium(wpa_s, cred_rc, 16947f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt bss, only_add); 169561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1696f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (cred_3gpp && 1697f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (cred == NULL || cred_prio_cmp(cred_3gpp, cred) >= 0)) { 16987f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return interworking_connect_3gpp(wpa_s, cred_3gpp, bss, 16997f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt only_add); 1700f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1701f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1702f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (cred == NULL) { 1703216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1704216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: No matching credentials found for " 1705216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 1706f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return -1; 1707f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1708f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 17094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt realm = nai_realm_parse(bss->anqp ? bss->anqp->nai_realm : NULL, 17104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt &count); 17111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (realm == NULL) { 1712216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1713216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Could not parse NAI Realm list from " 1714216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 1715f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return -1; 17161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 17171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1718f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt for (i = 0; i < count; i++) { 1719f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (!nai_realm_match(&realm[i], cred->realm)) 1720f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt continue; 1721807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt eap = nai_realm_find_eap(wpa_s, cred, &realm[i]); 17221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap) 17231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 17241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 17251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!eap) { 1727216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1728216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: No matching credentials and EAP method found for " 1729216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 17301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, count); 17311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 17321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 17331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1734216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Connect with " MACSTR, 1735216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt MAC2STR(bss->bssid)); 17361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17375460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (already_connected(wpa_s, cred, bss)) { 17385460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR, 17395460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt MAC2STR(bss->bssid)); 17405460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt nai_realm_free(realm, count); 17415460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return 0; 17425460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt } 17435460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 17445460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt remove_duplicate_network(wpa_s, cred, bss); 17455460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 17461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid = wpa_config_add_network(wpa_s->conf); 17471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ssid == NULL) { 17481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, count); 17491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 17501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1751d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt ssid->parent_cred = cred; 17521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpas_notify_network_added(wpa_s, ssid); 17531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_config_set_network_defaults(ssid); 175404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ssid->priority = cred->priority; 17551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid->temporary = 1; 17565460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt ssid->ssid = os_zalloc(bss->ssid_len + 1); 17571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ssid->ssid == NULL) 17581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 17595460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len); 17605460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt ssid->ssid_len = bss->ssid_len; 17611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1762d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (interworking_set_hs20_params(wpa_s, ssid) < 0) 176304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto fail; 176404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 176561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_config_set(ssid, "eap", eap_get_name(EAP_VENDOR_IETF, 176661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt eap->method), 0) < 0) 17671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 17681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (eap->method) { 17701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case EAP_TYPE_TTLS: 17711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->inner_method) { 17721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_snprintf(buf, sizeof(buf), "\"autheap=%s\"", 17731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_get_name(EAP_VENDOR_IETF, 17741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_method)); 17751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set(ssid, "phase2", buf, 0) < 0) 17761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 17771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 17781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 17791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (eap->inner_non_eap) { 17801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_PAP: 17811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set(ssid, "phase2", "\"auth=PAP\"", 0) < 17821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 0) 17831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 17841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 17851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_CHAP: 17861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set(ssid, "phase2", "\"auth=CHAP\"", 0) 17871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt < 0) 17881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 17891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 17901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_MSCHAP: 1791c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAP\"", 1792c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 0) < 0) 17931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 17941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 17951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_MSCHAPV2: 17961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAPV2\"", 17971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 0) < 0) 17981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 17991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 1800a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt default: 1801a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt /* EAP params were not set - assume TTLS/MSCHAPv2 */ 1802a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAPV2\"", 1803a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 0) < 0) 1804a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt goto fail; 1805a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt break; 18061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 18071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 18081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case EAP_TYPE_PEAP: 1809fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case EAP_TYPE_FAST: 1810fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (wpa_config_set(ssid, "phase1", "\"fast_provisioning=2\"", 1811fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 0) < 0) 1812fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt goto fail; 1813fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (wpa_config_set(ssid, "pac_file", 1814fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt "\"blob://pac_interworking\"", 0) < 0) 1815fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt goto fail; 181609f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt name = eap_get_name(EAP_VENDOR_IETF, 181709f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt eap->inner_method ? eap->inner_method : 181809f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt EAP_TYPE_MSCHAPV2); 181909f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt if (name == NULL) 182009f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt goto fail; 182109f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt os_snprintf(buf, sizeof(buf), "\"auth=%s\"", name); 18221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set(ssid, "phase2", buf, 0) < 0) 18231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 18241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 182504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case EAP_TYPE_TLS: 182604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 18271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 18281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 182961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (interworking_set_eap_params(ssid, cred, 183061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt eap->method == EAP_TYPE_TTLS) < 0) 18311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 18321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 18331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, count); 18341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1835f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->next_ssid = ssid; 183604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_config_update_prio_list(wpa_s->conf); 18377f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (!only_add) 18387f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt interworking_reconnect(wpa_s); 18391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 18407f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return ssid->id; 18411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 18421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtfail: 18431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpas_notify_network_removed(wpa_s, ssid); 18441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_config_remove_network(wpa_s->conf, ssid->id); 18451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, count); 18461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 18471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 18481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 18491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1850df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#ifdef PCSC_FUNCS 1851df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidtstatic int interworking_pcsc_read_imsi(struct wpa_supplicant *wpa_s) 1852df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt{ 1853df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt size_t len; 1854df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 1855df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (wpa_s->imsi[0] && wpa_s->mnc_len) 1856df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return 0; 1857df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 1858df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt len = sizeof(wpa_s->imsi) - 1; 1859df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) { 1860df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt scard_deinit(wpa_s->scard); 1861df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_s->scard = NULL; 1862df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI"); 1863df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 1864df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 1865df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_s->imsi[len] = '\0'; 1866df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard); 1867df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)", 1868df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_s->imsi, wpa_s->mnc_len); 1869df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 1870df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return 0; 1871df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt} 1872df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#endif /* PCSC_FUNCS */ 1873df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 1874df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 187504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic struct wpa_cred * interworking_credentials_available_3gpp( 1876f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 1877f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int *excluded) 18781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 18792f3b8dec59373945c5feef8a78ced8967a80cc66Dmitry Shmidt struct wpa_cred *selected = NULL; 18802f3b8dec59373945c5feef8a78ced8967a80cc66Dmitry Shmidt#ifdef INTERWORKING_3GPP 18812f3b8dec59373945c5feef8a78ced8967a80cc66Dmitry Shmidt struct wpa_cred *cred; 188204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int ret; 1883f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int is_excluded = 0; 18841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1885807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL) { 1886807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1887807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt "interworking-avail-3gpp: not avail, anqp: %p anqp_3gpp: %p", 1888807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt bss->anqp, bss->anqp ? bss->anqp->anqp_3gpp : NULL); 188904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 1890807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } 18911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1892b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt#ifdef CONFIG_EAP_PROXY 1893b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt if (!wpa_s->imsi[0]) { 1894b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt size_t len; 1895807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1896807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt "Interworking: IMSI not available - try to read again through eap_proxy"); 1897b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, 1898b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt wpa_s->imsi, 1899b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt &len); 1900b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt if (wpa_s->mnc_len > 0) { 1901b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt wpa_s->imsi[len] = '\0'; 1902807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1903807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt "eap_proxy: IMSI %s (MNC length %d)", 1904807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_s->imsi, wpa_s->mnc_len); 1905b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt } else { 1906807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1907807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt "eap_proxy: IMSI not available"); 1908b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt } 1909b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt } 1910b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt#endif /* CONFIG_EAP_PROXY */ 1911b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt 191204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 191304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char *sep; 191404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const char *imsi; 191504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int mnc_len; 191634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt char imsi_buf[16]; 191734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t msin_len; 191804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 191904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef PCSC_FUNCS 1920df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (cred->pcsc && wpa_s->scard) { 1921df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (interworking_pcsc_read_imsi(wpa_s) < 0) 1922df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt continue; 192304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt imsi = wpa_s->imsi; 192404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt mnc_len = wpa_s->mnc_len; 192504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto compare; 192604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 192704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* PCSC_FUNCS */ 192834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#ifdef CONFIG_EAP_PROXY 192934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (cred->pcsc && wpa_s->mnc_len > 0 && wpa_s->imsi[0]) { 193034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt imsi = wpa_s->imsi; 193134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt mnc_len = wpa_s->mnc_len; 193234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt goto compare; 193334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 193434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* CONFIG_EAP_PROXY */ 19351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 193604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->imsi == NULL || !cred->imsi[0] || 1937051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt (!wpa_s->conf->external_sim && 1938051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt (cred->milenage == NULL || !cred->milenage[0]))) 193904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 194004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 194104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sep = os_strchr(cred->imsi, '-'); 194204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (sep == NULL || 194304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (sep - cred->imsi != 5 && sep - cred->imsi != 6)) 194404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 194504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt mnc_len = sep - cred->imsi - 3; 194634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(imsi_buf, cred->imsi, 3 + mnc_len); 194734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt sep++; 194834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt msin_len = os_strlen(cred->imsi); 194934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (3 + mnc_len + msin_len >= sizeof(imsi_buf) - 1) 195034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt msin_len = sizeof(imsi_buf) - 3 - mnc_len - 1; 195134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(&imsi_buf[3 + mnc_len], sep, msin_len); 195234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt imsi_buf[3 + mnc_len + msin_len] = '\0'; 195334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt imsi = imsi_buf; 195434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 195534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#if defined(PCSC_FUNCS) || defined(CONFIG_EAP_PROXY) 195604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt compare: 195734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* PCSC_FUNCS || CONFIG_EAP_PROXY */ 1958216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 1959216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Parsing 3GPP info from " MACSTR, 1960216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt MAC2STR(bss->bssid)); 19614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt ret = plmn_id_match(bss->anqp->anqp_3gpp, imsi, mnc_len); 1962216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, "PLMN match %sfound", 1963216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt ret ? "" : "not "); 196404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (ret) { 1965051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (cred_no_required_oi_match(cred, bss)) 1966051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt continue; 1967f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && 1968f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_below_min_backhaul(wpa_s, cred, bss)) 1969f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1970f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && 1971f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_over_max_bss_load(wpa_s, cred, bss)) 1972f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1973f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && 1974f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_conn_capab_missing(wpa_s, cred, bss)) 1975f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1976f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred_excluded_ssid(cred, bss)) { 1977f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded == NULL) 1978f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1979f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected == NULL) { 1980f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = cred; 1981f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt is_excluded = 1; 1982f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1983f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 1984f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected == NULL || is_excluded || 1985f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_prio_cmp(selected, cred) < 0) { 1986f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = cred; 1987f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt is_excluded = 0; 1988f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1989f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 199004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 199104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 1992f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1993f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded) 1994f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt *excluded = is_excluded; 19951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* INTERWORKING_3GPP */ 199604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return selected; 19971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 19981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 200004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic struct wpa_cred * interworking_credentials_available_realm( 2001f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 2002f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int *excluded) 20031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 200404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_cred *cred, *selected = NULL; 20051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm *realm; 20061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 count, i; 2007f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int is_excluded = 0; 20081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 20094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp == NULL || bss->anqp->nai_realm == NULL) 201004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 20111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 201204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->conf->cred == NULL) 201304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 20141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2015216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Parsing NAI Realm list from " 2016216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 20174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt realm = nai_realm_parse(bss->anqp->nai_realm, &count); 20181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (realm == NULL) { 2019216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 2020216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Could not parse NAI Realm list from " 2021216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 202204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 20231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 20241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 202504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 202604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->realm == NULL) 20271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt continue; 202804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 202904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0; i < count; i++) { 203004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!nai_realm_match(&realm[i], cred->realm)) 203104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 2032807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (nai_realm_find_eap(wpa_s, cred, &realm[i])) { 2033051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (cred_no_required_oi_match(cred, bss)) 2034051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt continue; 2035f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && 2036f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_below_min_backhaul(wpa_s, cred, bss)) 2037f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 2038f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && 2039f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_over_max_bss_load(wpa_s, cred, bss)) 2040f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 2041f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && 2042f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_conn_capab_missing(wpa_s, cred, bss)) 2043f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 2044f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred_excluded_ssid(cred, bss)) { 2045f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded == NULL) 2046f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 2047f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected == NULL) { 2048f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = cred; 2049f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt is_excluded = 1; 2050f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2051f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 2052f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected == NULL || is_excluded || 2053f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_prio_cmp(selected, cred) < 0) 2054f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt { 2055f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = cred; 2056f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt is_excluded = 0; 2057f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2058f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 205904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 2060216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } else { 2061216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 2062216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: realm-find-eap returned false"); 206304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 20641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 20651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 20661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 20671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, count); 20681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2069f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded) 2070f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt *excluded = is_excluded; 2071f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 207204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return selected; 207304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 207404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 207504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2076f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic struct wpa_cred * interworking_credentials_available_helper( 2077f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 2078f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int *excluded) 207904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 208004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_cred *cred, *cred2; 20811d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt int excluded1, excluded2 = 0; 208204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 20835460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (disallowed_bssid(wpa_s, bss->bssid) || 20845460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) { 20855460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Ignore disallowed BSS " 20865460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 20875460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return NULL; 20885460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt } 20895460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 2090f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred = interworking_credentials_available_realm(wpa_s, bss, ignore_bw, 2091f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt &excluded1); 2092f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred2 = interworking_credentials_available_3gpp(wpa_s, bss, ignore_bw, 2093f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt &excluded2); 2094f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred && cred2 && 2095f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (cred_prio_cmp(cred2, cred) >= 0 || (!excluded2 && excluded1))) { 209604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred = cred2; 2097f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excluded1 = excluded2; 2098f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2099f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!cred) { 210004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred = cred2; 2101f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excluded1 = excluded2; 2102f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 210304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2104f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred2 = interworking_credentials_available_roaming_consortium( 2105f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s, bss, ignore_bw, &excluded2); 2106f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred && cred2 && 2107f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (cred_prio_cmp(cred2, cred) >= 0 || (!excluded2 && excluded1))) { 210861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred = cred2; 2109f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excluded1 = excluded2; 2110f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2111f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!cred) { 211261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred = cred2; 2113f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excluded1 = excluded2; 2114f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 211561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2116f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded) 2117f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt *excluded = excluded1; 211804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return cred; 21191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 21201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 21211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2122f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic struct wpa_cred * interworking_credentials_available( 2123f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int *excluded) 2124f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 2125f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred; 2126f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2127f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded) 2128f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt *excluded = 0; 2129f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred = interworking_credentials_available_helper(wpa_s, bss, 0, 2130f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excluded); 2131f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred) 2132f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return cred; 2133f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return interworking_credentials_available_helper(wpa_s, bss, 1, 2134f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excluded); 2135f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 2136f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2137f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2138f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtint domain_name_list_contains(struct wpabuf *domain_names, 2139f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt const char *domain, int exact_match) 21401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 214104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *pos, *end; 214204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt size_t len; 214304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 214404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt len = os_strlen(domain); 214504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos = wpabuf_head(domain_names); 214604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt end = pos + wpabuf_len(domain_names); 214704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2148d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt while (end - pos > 1) { 2149d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt u8 elen; 2150d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 2151d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt elen = *pos++; 2152d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (elen > end - pos) 215304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 215404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 215504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "Interworking: AP domain name", 2156d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt pos, elen); 2157d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (elen == len && 2158d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt os_strncasecmp(domain, (const char *) pos, len) == 0) 215904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 1; 2160d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (!exact_match && elen > len && pos[elen - len - 1] == '.') { 2161d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt const char *ap = (const char *) pos; 2162d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt int offset = elen - len; 2163d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 2164f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (os_strncasecmp(domain, ap + offset, len) == 0) 2165f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 2166f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 216704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2168d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt pos += elen; 216904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 217004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 217104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 217204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 217304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 217404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2175d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtint interworking_home_sp_cred(struct wpa_supplicant *wpa_s, 2176d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpa_cred *cred, 2177d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpabuf *domain_names) 217804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 2179051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt size_t i; 218068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt int ret = -1; 218104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef INTERWORKING_3GPP 218204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char nai[100], *realm; 218304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2184d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt char *imsi = NULL; 2185d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt int mnc_len = 0; 2186d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (cred->imsi) 2187d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt imsi = cred->imsi; 2188df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#ifdef PCSC_FUNCS 2189df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt else if (cred->pcsc && wpa_s->scard) { 2190df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (interworking_pcsc_read_imsi(wpa_s) < 0) 2191df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 2192d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt imsi = wpa_s->imsi; 2193d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt mnc_len = wpa_s->mnc_len; 2194d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 2195df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#endif /* PCSC_FUNCS */ 2196051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#ifdef CONFIG_EAP_PROXY 2197051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt else if (cred->pcsc && wpa_s->mnc_len > 0 && wpa_s->imsi[0]) { 2198051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt imsi = wpa_s->imsi; 2199051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt mnc_len = wpa_s->mnc_len; 2200051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 2201051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#endif /* CONFIG_EAP_PROXY */ 2202a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (domain_names && 2203a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt imsi && build_root_nai(nai, sizeof(nai), imsi, mnc_len, 0) == 0) { 2204d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt realm = os_strchr(nai, '@'); 2205d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (realm) 2206d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt realm++; 2207216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 2208216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Search for match with SIM/USIM domain %s", 2209216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt realm); 2210d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (realm && 2211f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt domain_name_list_contains(domain_names, realm, 1)) 2212d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 1; 221368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (realm) 221468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt ret = 0; 2215d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 221604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* INTERWORKING_3GPP */ 221704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2218a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (domain_names == NULL || cred->domain == NULL) 221968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return ret; 222004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2221051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt for (i = 0; i < cred->num_domain; i++) { 2222216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 2223216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Search for match with home SP FQDN %s", 2224216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt cred->domain[i]); 2225f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (domain_name_list_contains(domain_names, cred->domain[i], 1)) 2226051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 1; 2227051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 2228d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 2229d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 0; 2230d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt} 2231d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 2232d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 2233d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic int interworking_home_sp(struct wpa_supplicant *wpa_s, 2234d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpabuf *domain_names) 2235d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{ 2236d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpa_cred *cred; 2237d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 2238d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (domain_names == NULL || wpa_s->conf->cred == NULL) 2239d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return -1; 2240d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 2241d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 2242d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt int res = interworking_home_sp_cred(wpa_s, cred, domain_names); 2243d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (res) 2244d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return res; 224504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 224604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 224704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 224804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 224904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 225004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 225104949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int interworking_find_network_match(struct wpa_supplicant *wpa_s) 225204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 225304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_bss *bss; 225404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_ssid *ssid; 225504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 225604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 225704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 225804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpas_network_disabled(wpa_s, ssid) || 225904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ssid->mode != WPAS_MODE_INFRA) 226004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 226104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (ssid->ssid_len != bss->ssid_len || 226204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) != 226304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 0) 226404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 226504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 226604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * TODO: Consider more accurate matching of security 226704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * configuration similarly to what is done in events.c 226804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 226904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 1; 227004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 227104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 227204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 227304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 22741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 22751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 22761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2277f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int roaming_partner_match(struct wpa_supplicant *wpa_s, 2278f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct roaming_partner *partner, 2279f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpabuf *domain_names) 2280f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 2281f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Comparing roaming_partner info fqdn='%s' exact_match=%d priority=%u country='%s'", 2282f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt partner->fqdn, partner->exact_match, partner->priority, 2283f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt partner->country); 2284f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "Interworking: Domain names", 2285f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_head(domain_names), 2286f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_len(domain_names)); 2287f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!domain_name_list_contains(domain_names, partner->fqdn, 2288f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt partner->exact_match)) 2289f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; 2290f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* TODO: match Country */ 2291f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 2292f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 2293f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2294f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2295f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic u8 roaming_prio(struct wpa_supplicant *wpa_s, struct wpa_cred *cred, 2296f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_bss *bss) 2297f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 2298f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt size_t i; 2299f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2300f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (bss->anqp == NULL || bss->anqp->domain_name == NULL) { 2301f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: No ANQP domain name info -> use default roaming partner priority 128"); 2302f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 128; /* cannot check preference with domain name */ 2303f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2304f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2305f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (interworking_home_sp_cred(wpa_s, cred, bss->anqp->domain_name) > 0) 2306f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt { 2307f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Determined to be home SP -> use maximum preference 0 as roaming partner priority"); 2308f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* max preference for home SP network */ 2309f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2310f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2311f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (i = 0; i < cred->num_roaming_partner; i++) { 2312f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (roaming_partner_match(wpa_s, &cred->roaming_partner[i], 2313f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bss->anqp->domain_name)) { 2314f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Roaming partner preference match - priority %u", 2315f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->roaming_partner[i].priority); 2316f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return cred->roaming_partner[i].priority; 2317f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2318f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2319f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2320f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: No roaming partner preference match - use default roaming partner priority 128"); 2321f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 128; 2322f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 2323f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2324f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2325f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic struct wpa_bss * pick_best_roaming_partner(struct wpa_supplicant *wpa_s, 2326f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_bss *selected, 2327f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred) 2328f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 2329f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_bss *bss; 2330f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u8 best_prio, prio; 2331f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred2; 2332f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2333f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* 2334f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt * Check if any other BSS is operated by a more preferred roaming 2335f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt * partner. 2336f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt */ 2337f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2338f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt best_prio = roaming_prio(wpa_s, cred, selected); 2339f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: roaming_prio=%u for selected BSS " 2340f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MACSTR " (cred=%d)", best_prio, MAC2STR(selected->bssid), 2341f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->id); 2342f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2343f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 2344f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (bss == selected) 2345f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 2346f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred2 = interworking_credentials_available(wpa_s, bss, NULL); 2347f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!cred2) 2348f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 2349f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) 2350f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 2351f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt prio = roaming_prio(wpa_s, cred2, bss); 2352f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: roaming_prio=%u for BSS " 2353f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MACSTR " (cred=%d)", prio, MAC2STR(bss->bssid), 2354f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred2->id); 2355f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (prio < best_prio) { 2356f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int bh1, bh2, load1, load2, conn1, conn2; 2357f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bh1 = cred_below_min_backhaul(wpa_s, cred, selected); 2358f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt load1 = cred_over_max_bss_load(wpa_s, cred, selected); 2359f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt conn1 = cred_conn_capab_missing(wpa_s, cred, selected); 2360f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bh2 = cred_below_min_backhaul(wpa_s, cred2, bss); 2361f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt load2 = cred_over_max_bss_load(wpa_s, cred2, bss); 2362f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt conn2 = cred_conn_capab_missing(wpa_s, cred2, bss); 2363f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: old: %d %d %d new: %d %d %d", 2364f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bh1, load1, conn1, bh2, load2, conn2); 2365f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (bh1 || load1 || conn1 || !(bh2 || load2 || conn2)) { 2366f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Better roaming partner " MACSTR " selected", MAC2STR(bss->bssid)); 2367f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt best_prio = prio; 2368f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = bss; 2369f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2370f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2371f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2372f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2373f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return selected; 2374f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 2375f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2376f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 23771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_select_network(struct wpa_supplicant *wpa_s) 23781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 237904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_bss *bss, *selected = NULL, *selected_home = NULL; 2380f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_bss *selected2 = NULL, *selected2_home = NULL; 23811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt unsigned int count = 0; 238204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const char *type; 238304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int res; 2384f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred, *selected_cred = NULL; 2385f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *selected_home_cred = NULL; 2386f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *selected2_cred = NULL; 2387f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *selected2_home_cred = NULL; 23881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 23891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->network_select = 0; 23901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2391f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Select network (auto_select=%d)", 2392f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->auto_select); 23931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 2394f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int excluded = 0; 2395f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int bh, bss_load, conn_capab; 2396f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred = interworking_credentials_available(wpa_s, bss, 2397f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt &excluded); 239804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!cred) 23991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt continue; 2400216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 240161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) { 240261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 240361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * We currently support only HS 2.0 networks and those 240461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * are required to use WPA2-Enterprise. 240561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 2406216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 2407216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Credential match with " MACSTR 2408216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt " but network does not use RSN", 2409216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt MAC2STR(bss->bssid)); 241061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt continue; 241161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 2412f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!excluded) 2413f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt count++; 24144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt res = interworking_home_sp(wpa_s, bss->anqp ? 24154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss->anqp->domain_name : NULL); 241604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (res > 0) 241704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt type = "home"; 241804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt else if (res == 0) 241904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt type = "roaming"; 242004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt else 242104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt type = "unknown"; 2422f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bh = cred_below_min_backhaul(wpa_s, cred, bss); 2423f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bss_load = cred_over_max_bss_load(wpa_s, cred, bss); 2424f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt conn_capab = cred_conn_capab_missing(wpa_s, cred, bss); 2425f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "%s" MACSTR " type=%s%s%s%s id=%d priority=%d sp_priority=%d", 2426f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excluded ? INTERWORKING_BLACKLISTED : INTERWORKING_AP, 2427f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MAC2STR(bss->bssid), type, 2428f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bh ? " below_min_backhaul=1" : "", 2429f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bss_load ? " over_max_bss_load=1" : "", 2430f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt conn_capab ? " conn_capab_missing=1" : "", 2431f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->id, cred->priority, cred->sp_priority); 2432f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded) 2433f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 243461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_s->auto_select || 243561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt (wpa_s->conf->auto_interworking && 243661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_s->auto_network_select)) { 2437f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (bh || bss_load || conn_capab) { 2438f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected2_cred == NULL || 2439f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_prio_cmp(cred, selected2_cred) > 0) { 2440f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Mark as selected2"); 2441f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected2 = bss; 2442f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected2_cred = cred; 2443f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2444f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (res > 0 && 2445f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (selected2_home_cred == NULL || 2446f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_prio_cmp(cred, selected2_home_cred) > 2447f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 0)) { 2448f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Mark as selected2_home"); 2449f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected2_home = bss; 2450f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected2_home_cred = cred; 2451f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2452f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 2453f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected_cred == NULL || 2454f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_prio_cmp(cred, selected_cred) > 0) { 2455f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Mark as selected"); 2456f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = bss; 2457f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected_cred = cred; 2458f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2459f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (res > 0 && 2460f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (selected_home_cred == NULL || 2461f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_prio_cmp(cred, selected_home_cred) > 2462f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 0)) { 2463f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Mark as selected_home"); 2464f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected_home = bss; 2465f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected_home_cred = cred; 2466f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 246704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 246804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 246904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 247004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 247104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (selected_home && selected_home != selected && 2472f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected_home_cred && 2473f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (selected_cred == NULL || 2474f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_prio_cmp(selected_home_cred, selected_cred) >= 0)) { 247504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Prefer network operated by the Home SP */ 2476f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Overrided selected with selected_home"); 247704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt selected = selected_home; 2478f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected_cred = selected_home_cred; 2479f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2480f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2481f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!selected) { 2482f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected2_home) { 2483f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Use home BSS with BW limit mismatch since no other network could be selected"); 2484f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = selected2_home; 2485f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected_cred = selected2_home_cred; 2486f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else if (selected2) { 2487f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Use visited BSS with BW limit mismatch since no other network could be selected"); 2488f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = selected2; 2489f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected_cred = selected2_cred; 2490f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 24911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 24921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (count == 0) { 249404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 249504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * No matching network was found based on configured 249604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * credentials. Check whether any of the enabled network blocks 249704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * have matching APs. 249804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 249904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (interworking_find_network_match(wpa_s)) { 2500216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 2501216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Possible BSS match for enabled network configurations"); 2502717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (wpa_s->auto_select) { 250361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt interworking_reconnect(wpa_s); 2504717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt return; 2505717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt } 250661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 250761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 250861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_s->auto_network_select) { 2509216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 2510216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Continue scanning after ANQP fetch"); 251161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_supplicant_req_scan(wpa_s, wpa_s->scan_interval, 251261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 0); 251304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 251404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 251504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 25161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, INTERWORKING_NO_MATCH "No network " 25171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "with matching credentials found"); 2518203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (wpa_s->wpa_state == WPA_SCANNING) 2519203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 25201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 25211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2522f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected) { 2523f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Selected " MACSTR, 2524f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MAC2STR(selected->bssid)); 2525f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = pick_best_roaming_partner(wpa_s, selected, 2526f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected_cred); 2527f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Selected " MACSTR 2528f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt " (after best roaming partner selection)", 2529f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MAC2STR(selected->bssid)); 2530f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, INTERWORKING_SELECTED MACSTR, 2531f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MAC2STR(selected->bssid)); 25327f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt interworking_connect(wpa_s, selected, 0); 2533293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt } else if (wpa_s->wpa_state == WPA_SCANNING) 2534293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 25351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 25361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic struct wpa_bss_anqp * 25394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtinterworking_match_anqp_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) 25404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 25414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_bss *other; 25424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 25434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (is_zero_ether_addr(bss->hessid)) 25444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return NULL; /* Cannot be in the same homegenous ESS */ 25454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 25464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt dl_list_for_each(other, &wpa_s->bss, struct wpa_bss, list) { 25474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (other == bss) 25484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 25494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (other->anqp == NULL) 25504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 2551a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (other->anqp->roaming_consortium == NULL && 2552a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt other->anqp->nai_realm == NULL && 2553a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt other->anqp->anqp_3gpp == NULL && 2554a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt other->anqp->domain_name == NULL) 2555a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt continue; 25564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!(other->flags & WPA_BSS_ANQP_FETCH_TRIED)) 25574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 25584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (os_memcmp(bss->hessid, other->hessid, ETH_ALEN) != 0) 25594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 25604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->ssid_len != other->ssid_len || 25614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_memcmp(bss->ssid, other->ssid, bss->ssid_len) != 0) 25624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 25634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 2564216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 2565216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Share ANQP data with already fetched BSSID " 2566216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt MACSTR " and " MACSTR, 2567216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt MAC2STR(other->bssid), MAC2STR(bss->bssid)); 25684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt other->anqp->users++; 25694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return other->anqp; 25704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 25714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 25724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return NULL; 25734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 25744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 25754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 25761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s) 25771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 25781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_bss *bss; 25791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int found = 0; 25801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *ie; 25811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2582f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: next_anqp_fetch - " 2583f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "fetch_anqp_in_progress=%d fetch_osu_icon_in_progress=%d", 2584f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->fetch_anqp_in_progress, 2585f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->fetch_osu_icon_in_progress); 2586f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2587f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (eloop_terminated() || !wpa_s->fetch_anqp_in_progress) { 2588f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Stop next-ANQP-fetch"); 2589f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return; 2590f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2591f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2592d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef CONFIG_HS20 2593f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (wpa_s->fetch_osu_icon_in_progress) { 2594f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Next icon (in progress)"); 2595f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt hs20_next_osu_icon(wpa_s); 25961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 2597f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2598d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* CONFIG_HS20 */ 25991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 26011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!(bss->caps & IEEE80211_CAP_ESS)) 26021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt continue; 26031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB); 26041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ie == NULL || ie[1] < 4 || !(ie[5] & 0x80)) 26051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt continue; /* AP does not support Interworking */ 26065460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (disallowed_bssid(wpa_s, bss->bssid) || 26075460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) 26085460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt continue; /* Disallowed BSS */ 26091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!(bss->flags & WPA_BSS_ANQP_FETCH_TRIED)) { 26114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp == NULL) { 26124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss->anqp = interworking_match_anqp_info(wpa_s, 26134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss); 26144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp) { 26154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Shared data already fetched */ 26164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 26174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 26184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss->anqp = wpa_bss_anqp_alloc(); 26194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp == NULL) 26204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt break; 26214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 26221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt found++; 26231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bss->flags |= WPA_BSS_ANQP_FETCH_TRIED; 26241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "Starting ANQP fetch for " 26251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 26261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_anqp_send_req(wpa_s, bss); 26271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 26281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 26291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 26301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (found == 0) { 2632d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef CONFIG_HS20 2633f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (wpa_s->fetch_osu_info) { 2634f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (wpa_s->num_prov_found == 0 && 26356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_s->fetch_osu_waiting_scan && 2636f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->num_osu_scans < 3) { 2637f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "HS 2.0: No OSU providers seen - try to scan again"); 2638f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt hs20_start_osu_scan(wpa_s); 2639f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return; 2640f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2641f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Next icon"); 2642f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt hs20_osu_icon_fetch(wpa_s); 2643f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return; 2644f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2645d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* CONFIG_HS20 */ 26461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "ANQP fetch completed"); 26471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->fetch_anqp_in_progress = 0; 26481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->network_select) 26491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_select_network(wpa_s); 26501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 26511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 26521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 265461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid interworking_start_fetch_anqp(struct wpa_supplicant *wpa_s) 26551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 26561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_bss *bss; 26571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) 26591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bss->flags &= ~WPA_BSS_ANQP_FETCH_TRIED; 26601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->fetch_anqp_in_progress = 1; 26622f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 26632f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt /* 26642f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt * Start actual ANQP operation from eloop call to make sure the loop 26652f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt * does not end up using excessive recursion. 26662f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt */ 26672f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt eloop_register_timeout(0, 0, interworking_continue_anqp, wpa_s, NULL); 26681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 26691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint interworking_fetch_anqp(struct wpa_supplicant *wpa_s) 26721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 26731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) 26741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 26751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->network_select = 0; 26774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_s->fetch_all_anqp = 1; 2678f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->fetch_osu_info = 0; 26791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_start_fetch_anqp(wpa_s); 26811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 26831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 26841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s) 26871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 26881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!wpa_s->fetch_anqp_in_progress) 26891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 26901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->fetch_anqp_in_progress = 0; 26921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 26931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, 26969839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt u16 info_ids[], size_t num_ids, u32 subtypes, 26979839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt int get_cell_pref) 26981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 26991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf; 27009839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt struct wpabuf *extra_buf = NULL; 27011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret = 0; 27021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int freq; 27031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_bss *bss; 27041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int res; 27051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 27061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bss = wpa_bss_get_bssid(wpa_s, dst); 2707cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt if (!bss) { 2708cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt wpa_printf(MSG_WARNING, 2709cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt "ANQP: Cannot send query to unknown BSS " 2710cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt MACSTR, MAC2STR(dst)); 27111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 2712cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt } 2713cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt 2714cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt wpa_bss_anqp_unshare_alloc(bss); 2715cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt freq = bss->freq; 27161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2717216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 2718216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "ANQP: Query Request to " MACSTR " for %u id(s)", 2719216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt MAC2STR(dst), (unsigned int) num_ids); 27201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 272115907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt#ifdef CONFIG_HS20 272215907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt if (subtypes != 0) { 27239839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt extra_buf = wpabuf_alloc(100); 27249839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt if (extra_buf == NULL) 272515907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt return -1; 27269839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt hs20_put_anqp_req(subtypes, NULL, 0, extra_buf); 272715907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt } 272815907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt#endif /* CONFIG_HS20 */ 272915907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt 27309839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt#ifdef CONFIG_MBO 27319839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt if (get_cell_pref) { 27329839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt struct wpabuf *mbo; 27339839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt 27349839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt mbo = mbo_build_anqp_buf(wpa_s, bss); 27359839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt if (mbo) { 27369839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt if (wpabuf_resize(&extra_buf, wpabuf_len(mbo))) { 27379839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt wpabuf_free(extra_buf); 27389839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt return -1; 27399839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt } 27409839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt wpabuf_put_buf(extra_buf, mbo); 27419839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt wpabuf_free(mbo); 27429839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt } 27439839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt } 27449839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt#endif /* CONFIG_MBO */ 27459839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt 27469839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt buf = anqp_build_req(info_ids, num_ids, extra_buf); 27479839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt wpabuf_free(extra_buf); 27481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL) 27491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 27501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 27511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s); 27521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (res < 0) { 2753216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request"); 2754051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpabuf_free(buf); 27551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = -1; 2756216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } else { 2757216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 2758216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "ANQP: Query started with dialog token %u", res); 2759216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 27601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 27611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ret; 27621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 27631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 27641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2765d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void anqp_add_extra(struct wpa_supplicant *wpa_s, 2766d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct wpa_bss_anqp *anqp, u16 info_id, 2767d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt const u8 *data, size_t slen) 2768d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{ 2769d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct wpa_bss_anqp_elem *tmp, *elem = NULL; 2770d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 2771d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (!anqp) 2772d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return; 2773d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 2774d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt dl_list_for_each(tmp, &anqp->anqp_elems, struct wpa_bss_anqp_elem, 2775d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt list) { 2776d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (tmp->infoid == info_id) { 2777d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt elem = tmp; 2778d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt break; 2779d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 2780d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 2781d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 2782d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (!elem) { 2783d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt elem = os_zalloc(sizeof(*elem)); 2784d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (!elem) 2785d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return; 2786d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt elem->infoid = info_id; 2787d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt dl_list_add(&anqp->anqp_elems, &elem->list); 2788d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } else { 2789d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpabuf_free(elem->payload); 2790d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 2791d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 2792d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt elem->payload = wpabuf_alloc_copy(data, slen); 2793d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (!elem->payload) { 2794d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt dl_list_del(&elem->list); 2795d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt os_free(elem); 2796d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 2797d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt} 2798d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 2799d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 28001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, 2801444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt struct wpa_bss *bss, const u8 *sa, 2802444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt u16 info_id, 28030e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt const u8 *data, size_t slen, 28040e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt u8 dialog_token) 28051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 28061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *pos = data; 28074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_bss_anqp *anqp = NULL; 280804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_HS20 280904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 type; 281004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_HS20 */ 28111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 28124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss) 28134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp = bss->anqp; 28144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 28151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (info_id) { 28161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_CAPABILITY_LIST: 281758d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 28181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " ANQP Capability list", MAC2STR(sa)); 28197f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Capability list", 28207f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt pos, slen); 28217f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (anqp) { 28227f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpabuf_free(anqp->capability_list); 28237f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt anqp->capability_list = wpabuf_alloc_copy(pos, slen); 28247f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 28251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 28261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_VENUE_NAME: 282758d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 28281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " Venue Name", MAC2STR(sa)); 28291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Venue Name", pos, slen); 28304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 28314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->venue_name); 28324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->venue_name = wpabuf_alloc_copy(pos, slen); 28331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 28341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 28351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_NETWORK_AUTH_TYPE: 283658d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 28371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " Network Authentication Type information", 28381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(sa)); 28391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Network Authentication " 28401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Type", pos, slen); 28414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 28424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->network_auth_type); 28434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->network_auth_type = wpabuf_alloc_copy(pos, slen); 28441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 28451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 28461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_ROAMING_CONSORTIUM: 284758d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 28481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " Roaming Consortium list", MAC2STR(sa)); 28491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Roaming Consortium", 28501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos, slen); 28514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 28524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->roaming_consortium); 28534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->roaming_consortium = wpabuf_alloc_copy(pos, slen); 28541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 28551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 28561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_IP_ADDR_TYPE_AVAILABILITY: 285758d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 28581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " IP Address Type Availability information", 28591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(sa)); 28601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "ANQP: IP Address Availability", 28611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos, slen); 28624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 28634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->ip_addr_type_availability); 28644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->ip_addr_type_availability = 28651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_alloc_copy(pos, slen); 28661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 28671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 28681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_NAI_REALM: 286958d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 28701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " NAI Realm list", MAC2STR(sa)); 28711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "ANQP: NAI Realm", pos, slen); 28724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 28734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->nai_realm); 28744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->nai_realm = wpabuf_alloc_copy(pos, slen); 28751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 28761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 28771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_3GPP_CELLULAR_NETWORK: 287858d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 28791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " 3GPP Cellular Network information", MAC2STR(sa)); 28801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "ANQP: 3GPP Cellular Network", 28811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos, slen); 28824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 28834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->anqp_3gpp); 28844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->anqp_3gpp = wpabuf_alloc_copy(pos, slen); 28851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 28861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 28871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_DOMAIN_NAME: 288858d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 28891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " Domain Name list", MAC2STR(sa)); 28901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: Domain Name", pos, slen); 28914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 28924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->domain_name); 28934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->domain_name = wpabuf_alloc_copy(pos, slen); 28941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 28951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 2896293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt#ifdef CONFIG_FILS 2897293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt case ANQP_FILS_REALM_INFO: 2898293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR 2899293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt " FILS Realm Information", MAC2STR(sa)); 2900293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: FILS Realm Information", 2901293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt pos, slen); 2902293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (anqp) { 2903293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt wpabuf_free(anqp->fils_realm_info); 2904293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt anqp->fils_realm_info = wpabuf_alloc_copy(pos, slen); 2905293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt } 2906293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt break; 2907293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt#endif /* CONFIG_FILS */ 29081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_VENDOR_SPECIFIC: 29091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (slen < 3) 29101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 29111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 29121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (WPA_GET_BE24(pos)) { 291304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_HS20 291404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case OUI_WFA: 291504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += 3; 291604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt slen -= 3; 291704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 291804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (slen < 1) 291904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 292004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt type = *pos++; 292104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt slen--; 292204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 292304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt switch (type) { 292404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case HS20_ANQP_OUI_TYPE: 29252f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt hs20_parse_rx_hs20_anqp_resp(wpa_s, bss, sa, 29260e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt pos, slen, 29270e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt dialog_token); 292804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 292904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt default: 2930216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 2931216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "HS20: Unsupported ANQP vendor type %u", 2932216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt type); 293304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 293404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 293504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 293604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_HS20 */ 29371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt default: 2938216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 2939216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Unsupported vendor-specific ANQP OUI %06x", 2940216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt WPA_GET_BE24(pos)); 29411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 29421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 29431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 29441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt default: 2945216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 2946216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Unsupported ANQP Info ID %u", info_id); 2947d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt anqp_add_extra(wpa_s, anqp, info_id, data, slen); 29481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 29491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 29501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 29511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 29521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 29531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token, 29541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt enum gas_query_result result, 29551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct wpabuf *adv_proto, 29561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct wpabuf *resp, u16 status_code) 29571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 29581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_supplicant *wpa_s = ctx; 29591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *pos; 29601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *end; 29611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 info_id; 29621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 slen; 2963444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt struct wpa_bss *bss = NULL, *tmp; 29642f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt const char *anqp_result = "SUCCESS"; 29651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2966f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: anqp_resp_cb dst=" MACSTR 2967f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt " dialog_token=%u result=%d status_code=%u", 2968f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MAC2STR(dst), dialog_token, result, status_code); 2969f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (result != GAS_QUERY_SUCCESS) { 2970d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef CONFIG_HS20 2971f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (wpa_s->fetch_osu_icon_in_progress) 2972f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt hs20_icon_fetch_failed(wpa_s); 2973d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* CONFIG_HS20 */ 29742f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt anqp_result = "FAILURE"; 29752f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt goto out; 2976f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 29771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 29781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = wpabuf_head(adv_proto); 29791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpabuf_len(adv_proto) < 4 || pos[0] != WLAN_EID_ADV_PROTO || 29801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos[1] < 2 || pos[3] != ACCESS_NETWORK_QUERY_PROTOCOL) { 2981216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 2982216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "ANQP: Unexpected Advertisement Protocol in response"); 2983d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef CONFIG_HS20 2984f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (wpa_s->fetch_osu_icon_in_progress) 2985f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt hs20_icon_fetch_failed(wpa_s); 2986d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* CONFIG_HS20 */ 29872f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt anqp_result = "INVALID_FRAME"; 29882f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt goto out; 29891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 29901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2991444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt /* 2992444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt * If possible, select the BSS entry based on which BSS entry was used 2993444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt * for the request. This can help in cases where multiple BSS entries 2994444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt * may exist for the same AP. 2995444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt */ 2996444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt dl_list_for_each_reverse(tmp, &wpa_s->bss, struct wpa_bss, list) { 2997444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (tmp == wpa_s->interworking_gas_bss && 2998444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt os_memcmp(tmp->bssid, dst, ETH_ALEN) == 0) { 2999444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt bss = tmp; 3000444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt break; 3001444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 3002444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 3003444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (bss == NULL) 3004444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt bss = wpa_bss_get_bssid(wpa_s, dst); 3005444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt 30061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = wpabuf_head(resp); 30071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = pos + wpabuf_len(resp); 30081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 30091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (pos < end) { 30106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt unsigned int left = end - pos; 30116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 30126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (left < 4) { 3013216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Invalid element"); 30142f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt anqp_result = "INVALID_FRAME"; 30152f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt goto out_parse_done; 30161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 30171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt info_id = WPA_GET_LE16(pos); 30181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 30191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt slen = WPA_GET_LE16(pos); 30201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 30216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt left -= 4; 30226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (left < slen) { 3023216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 3024216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "ANQP: Invalid element length for Info ID %u", 3025216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt info_id); 30262f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt anqp_result = "INVALID_FRAME"; 30272f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt goto out_parse_done; 30281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3029444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt interworking_parse_rx_anqp_resp(wpa_s, bss, dst, info_id, pos, 30300e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt slen, dialog_token); 30311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += slen; 30321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3033f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 30342f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidtout_parse_done: 3035d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef CONFIG_HS20 3036f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt hs20_notify_parse_done(wpa_s); 3037d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* CONFIG_HS20 */ 30382f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidtout: 30392f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, ANQP_QUERY_DONE "addr=" MACSTR " result=%s", 30402f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt MAC2STR(dst), anqp_result); 304104a9d74743634109939ddb9bc40814681a03dc84Roshan Pius wpas_notify_anqp_query_done(wpa_s, dst, anqp_result, bss ? bss->anqp : NULL); 30421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 30431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 30441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 30451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_scan_res_handler(struct wpa_supplicant *wpa_s, 30461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_scan_results *scan_res) 30471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 3048216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 3049216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Scan results available - start ANQP fetch"); 30501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_start_fetch_anqp(wpa_s); 30511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 30521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 30531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3054fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtint interworking_select(struct wpa_supplicant *wpa_s, int auto_select, 3055fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt int *freqs) 30561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 30571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_stop_fetch_anqp(wpa_s); 30581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->network_select = 1; 305961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_s->auto_network_select = 0; 30601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->auto_select = !!auto_select; 30614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_s->fetch_all_anqp = 0; 3062f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->fetch_osu_info = 0; 3063216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 3064216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "Interworking: Start scan for network selection"); 30651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->scan_res_handler = interworking_scan_res_handler; 306668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_s->normal_scans = 0; 3067d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_s->scan_req = MANUAL_SCAN_REQ; 3068fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_free(wpa_s->manual_scan_freqs); 3069fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->manual_scan_freqs = freqs; 307068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_s->after_wps = 0; 307168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_s->known_wps_freq = 0; 30721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_req_scan(wpa_s, 0, 0); 30731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 30741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 30751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 307661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 307761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 307861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, 307961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt enum gas_query_result result, 308061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const struct wpabuf *adv_proto, 308161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const struct wpabuf *resp, u16 status_code) 308261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 308361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_supplicant *wpa_s = ctx; 3084fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpabuf *n; 308561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 308661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, GAS_RESPONSE_INFO "addr=" MACSTR 308761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt " dialog_token=%d status_code=%d resp_len=%d", 308861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt MAC2STR(addr), dialog_token, status_code, 308961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt resp ? (int) wpabuf_len(resp) : -1); 309061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!resp) 309161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 309261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 3093fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt n = wpabuf_dup(resp); 3094fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (n == NULL) 309561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 3096fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpabuf_free(wpa_s->prev_gas_resp); 3097fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->prev_gas_resp = wpa_s->last_gas_resp; 3098fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_memcpy(wpa_s->prev_gas_addr, wpa_s->last_gas_addr, ETH_ALEN); 3099fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->prev_gas_dialog_token = wpa_s->last_gas_dialog_token; 3100fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->last_gas_resp = n; 310161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(wpa_s->last_gas_addr, addr, ETH_ALEN); 310261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_s->last_gas_dialog_token = dialog_token; 310361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 310461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 310561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 310661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst, 310761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const struct wpabuf *adv_proto, 310861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const struct wpabuf *query) 310961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 311061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *buf; 311161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int ret = 0; 311261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int freq; 311361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_bss *bss; 311461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int res; 311561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t len; 31167f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt u8 query_resp_len_limit = 0; 311761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 311861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt freq = wpa_s->assoc_freq; 311961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt bss = wpa_bss_get_bssid(wpa_s, dst); 312061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (bss) 312161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt freq = bss->freq; 312261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (freq <= 0) 312361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 312461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 3125216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, "GAS request to " MACSTR " (freq %d MHz)", 3126216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt MAC2STR(dst), freq); 312761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "Advertisement Protocol ID", adv_proto); 312861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "GAS Query", query); 312961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 313061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len = 3 + wpabuf_len(adv_proto) + 2; 313161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (query) 313261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len += wpabuf_len(query); 313361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt buf = gas_build_initial_req(0, len); 313461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (buf == NULL) 313561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 313661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 313761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Advertisement Protocol IE */ 313861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO); 313961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, 1 + wpabuf_len(adv_proto)); /* Length */ 31407f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt wpabuf_put_u8(buf, query_resp_len_limit & 0x7f); 314161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(buf, adv_proto); 314261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 314361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* GAS Query */ 314461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (query) { 314561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, wpabuf_len(query)); 314661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(buf, query); 314761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else 314861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, 0); 314961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 315061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt res = gas_query_req(wpa_s->gas, dst, freq, buf, gas_resp_cb, wpa_s); 315161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (res < 0) { 3152216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request"); 3153051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpabuf_free(buf); 315461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ret = -1; 315561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else 3156216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, 3157216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt "GAS: Query started with dialog token %u", res); 315861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 315961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return ret; 316061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 3161