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{ 7604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->wpa_state >= WPA_AUTHENTICATING) { 7704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_supplicant_cancel_sched_scan(wpa_s); 7804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_supplicant_deauthenticate(wpa_s, 7904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt WLAN_REASON_DEAUTH_LEAVING); 8004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 8104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->disconnected = 0; 8204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->reassociate = 1; 834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 844b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (wpa_supplicant_fast_associate(wpa_s) >= 0) 854b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return; 864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 8704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_supplicant_req_scan(wpa_s, 0, 0); 8804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 8904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 9004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct wpabuf * anqp_build_req(u16 info_ids[], size_t num_ids, 921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *extra) 931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf; 951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t i; 961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *len_pos; 971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf = gas_anqp_build_initial_req(0, 4 + num_ids * 2 + 991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (extra ? wpabuf_len(extra) : 0)); 1001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL) 1011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 1021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len_pos = gas_anqp_add_element(buf, ANQP_QUERY_LIST); 1041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < num_ids; i++) 1051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_le16(buf, info_ids[i]); 1061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt gas_anqp_set_element_len(buf, len_pos); 1071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (extra) 1081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_buf(buf, extra); 1091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt gas_anqp_set_len(buf); 1111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return buf; 1131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 1141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_anqp_resp_cb(void *ctx, const u8 *dst, 1171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 dialog_token, 1181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt enum gas_query_result result, 1191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct wpabuf *adv_proto, 1201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct wpabuf *resp, 1211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 status_code) 1221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_supplicant *wpa_s = ctx; 1241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 125f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Response callback dst=" MACSTR 126f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt " dialog_token=%u result=%d status_code=%u", 127f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MAC2STR(dst), dialog_token, result, status_code); 1281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt anqp_resp_cb(wpa_s, dst, dialog_token, result, adv_proto, resp, 1291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt status_code); 1301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_next_anqp_fetch(wpa_s); 1311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 1321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int cred_with_roaming_consortium(struct wpa_supplicant *wpa_s) 1354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_cred *cred; 1374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 1394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->roaming_consortium_len) 1404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 1; 141051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (cred->required_roaming_consortium_len) 142051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 1; 1434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 1454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 1464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int cred_with_3gpp(struct wpa_supplicant *wpa_s) 1494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_cred *cred; 1514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 1534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->pcsc || cred->imsi) 1544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 1; 1554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 1574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 1584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int cred_with_nai_realm(struct wpa_supplicant *wpa_s) 1614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_cred *cred; 1634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 1654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->pcsc || cred->imsi) 1664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 1674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!cred->eap_method) 1684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 1; 1694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->realm && cred->roaming_consortium_len == 0) 1704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 1; 1714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 1734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 1744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int cred_with_domain(struct wpa_supplicant *wpa_s) 1774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_cred *cred; 1794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 181f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred->domain || cred->pcsc || cred->imsi || 182f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->roaming_partner) 183f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 184f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 185f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; 186f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 187f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 188f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 189f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_HS20 190f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 191f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int cred_with_min_backhaul(struct wpa_supplicant *wpa_s) 192f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 193f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred; 194f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 195f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 196f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred->min_dl_bandwidth_home || 197f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->min_ul_bandwidth_home || 198f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->min_dl_bandwidth_roaming || 199f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->min_ul_bandwidth_roaming) 2004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 1; 2014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 2024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 2034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 2044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 2054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 206f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int cred_with_conn_capab(struct wpa_supplicant *wpa_s) 207f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 208f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred; 209f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 210f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 211f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred->num_req_conn_capab) 212f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 213f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 214f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; 215f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 216f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 217f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_HS20 */ 218f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 219f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int additional_roaming_consortiums(struct wpa_bss *bss) 2214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 2224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt const u8 *ie; 2234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM); 2244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ie == NULL || ie[1] == 0) 2254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 2264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return ie[2]; /* Number of ANQP OIs */ 2274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 2284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 2294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 230a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic void interworking_continue_anqp(void *eloop_ctx, void *sock_ctx) 231a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{ 232a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt struct wpa_supplicant *wpa_s = eloop_ctx; 233a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt interworking_next_anqp_fetch(wpa_s); 234a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt} 235a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 236a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 2371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int interworking_anqp_send_req(struct wpa_supplicant *wpa_s, 2381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_bss *bss) 2391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf; 2411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret = 0; 2421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int res; 2434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt u16 info_ids[8]; 2444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt size_t num_info_ids = 0; 2451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *extra = NULL; 2464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int all = wpa_s->fetch_all_anqp; 2471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: ANQP Query Request to " MACSTR, 2491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(bss->bssid)); 250444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt wpa_s->interworking_gas_bss = bss; 2511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_CAPABILITY_LIST; 2534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all) { 2544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_VENUE_NAME; 2554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_NETWORK_AUTH_TYPE; 2564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 2574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all || (cred_with_roaming_consortium(wpa_s) && 2584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt additional_roaming_consortiums(bss))) 2594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_ROAMING_CONSORTIUM; 2604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all) 2614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_IP_ADDR_TYPE_AVAILABILITY; 2624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all || cred_with_nai_realm(wpa_s)) 2634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_NAI_REALM; 264df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (all || cred_with_3gpp(wpa_s)) { 2654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_3GPP_CELLULAR_NETWORK; 266df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_supplicant_scard_init(wpa_s, NULL); 267df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 2684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (all || cred_with_domain(wpa_s)) 2694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt info_ids[num_info_ids++] = ANQP_DOMAIN_NAME; 2704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "Interworking: ANQP Query info", 2714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt (u8 *) info_ids, num_info_ids * 2); 2724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 27304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_HS20 27404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) { 27504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 *len_pos; 27604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 27704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt extra = wpabuf_alloc(100); 27804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!extra) 27904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 28004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 28104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt len_pos = gas_anqp_add_element(extra, ANQP_VENDOR_SPECIFIC); 28204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_be24(extra, OUI_WFA); 28304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(extra, HS20_ANQP_OUI_TYPE); 28404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_QUERY_LIST); 28504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(extra, 0); /* Reserved */ 28604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_CAPABILITY_LIST); 287f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (all) 2884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_put_u8(extra, 2894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt HS20_STYPE_OPERATOR_FRIENDLY_NAME); 290f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (all || cred_with_min_backhaul(wpa_s)) 2914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_WAN_METRICS); 292f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (all || cred_with_conn_capab(wpa_s)) 2934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_CONNECTION_CAPABILITY); 294f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (all) 2954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_OPERATING_CLASS); 296f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (all) 297f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_LIST); 29804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt gas_anqp_set_element_len(extra, len_pos); 29904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 30004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_HS20 */ 30104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 3024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt buf = anqp_build_req(info_ids, num_info_ids, extra); 3031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_free(extra); 3041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL) 3051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 3061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, buf, 3081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_anqp_resp_cb, wpa_s); 3091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (res < 0) { 3101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request"); 311051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpabuf_free(buf); 3121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = -1; 313a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt eloop_register_timeout(0, 0, interworking_continue_anqp, wpa_s, 314a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt NULL); 3151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else 3161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token " 3171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "%u", res); 3181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ret; 3201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 3211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct nai_realm_eap { 3241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 method; 3251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 inner_method; 3261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt enum nai_realm_eap_auth_inner_non_eap inner_non_eap; 3271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 cred_type; 3281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 tunneled_cred_type; 3291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}; 3301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct nai_realm { 3321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 encoding; 3331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt char *realm; 3341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 eap_count; 3351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm_eap *eap; 3361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}; 3371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void nai_realm_free(struct nai_realm *realms, u16 count) 3401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 3411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 i; 3421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (realms == NULL) 3441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 3451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < count; i++) { 3461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(realms[i].eap); 3471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(realms[i].realm); 3481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(realms); 3501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 3511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic const u8 * nai_realm_parse_eap(struct nai_realm_eap *e, const u8 *pos, 3541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *end) 3551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 3561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 elen, auth_count, a; 3571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *e_end; 3581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + 3 > end) { 3601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for EAP Method fixed fields"); 3611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 3621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt elen = *pos++; 3651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + elen > end || elen < 2) { 3661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for EAP Method subfield"); 3671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 3681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e_end = pos + elen; 3701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->method = *pos++; 3711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt auth_count = *pos++; 3721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP Method: len=%u method=%u auth_count=%u", 3731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt elen, e->method, auth_count); 3741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (a = 0; a < auth_count; a++) { 3761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 id, len; 3771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + 2 > end || pos + 2 + pos[1] > end) { 3791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for Authentication " 3801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Parameter subfield"); 3811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 3821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt id = *pos++; 3851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = *pos++; 3861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (id) { 3881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_EAP_AUTH_NON_EAP_INNER_AUTH: 3891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < 1) 3901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->inner_non_eap = *pos; 3921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (e->method != EAP_TYPE_TTLS) 3931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (*pos) { 3951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_PAP: 3961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP"); 3971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_CHAP: 3991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP"); 4001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_MSCHAP: 4021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP"); 4031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_MSCHAPV2: 4051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2"); 4061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_EAP_AUTH_INNER_AUTH_EAP_METHOD: 4101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < 1) 4111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->inner_method = *pos; 4131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Inner EAP method: %u", 4141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->inner_method); 4151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_EAP_AUTH_CRED_TYPE: 4171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < 1) 4181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->cred_type = *pos; 4201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Credential Type: %u", 4211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->cred_type); 4221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_EAP_AUTH_TUNNELED_CRED_TYPE: 4241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < 1) 4251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt e->tunneled_cred_type = *pos; 4271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Tunneled EAP Method Credential " 4281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Type: %u", e->tunneled_cred_type); 4291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt default: 4311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Unsupported Authentication " 4321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Parameter: id=%u len=%u", id, len); 4331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump(MSG_DEBUG, "Authentication Parameter " 4341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Value", pos, len); 4351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += len; 4391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return e_end; 4421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 4431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic const u8 * nai_realm_parse_realm(struct nai_realm *r, const u8 *pos, 4461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *end) 4471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 4481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 len; 4491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *f_end; 4501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 realm_len, e; 4511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (end - pos < 4) { 4531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for NAI Realm Data " 4541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "fixed fields"); 4551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = WPA_GET_LE16(pos); /* NAI Realm Data field Length */ 4591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 4601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + len > end || len < 3) { 4611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for NAI Realm Data " 4621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "(len=%u; left=%u)", 4631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len, (unsigned int) (end - pos)); 4641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt f_end = pos + len; 4671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt r->encoding = *pos++; 4691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt realm_len = *pos++; 4701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + realm_len > f_end) { 4711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for NAI Realm " 4721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "(len=%u; left=%u)", 4731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt realm_len, (unsigned int) (f_end - pos)); 4741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "NAI Realm", pos, realm_len); 4774b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt r->realm = dup_binstr(pos, realm_len); 4781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (r->realm == NULL) 4791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += realm_len; 4811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + 1 > f_end) { 4831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for EAP Method Count"); 4841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt r->eap_count = *pos++; 4871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP Count: %u", r->eap_count); 4881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + r->eap_count * 3 > f_end) { 4891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No room for EAP Methods"); 4901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 49261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt r->eap = os_calloc(r->eap_count, sizeof(struct nai_realm_eap)); 4931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (r->eap == NULL) 4941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (e = 0; e < r->eap_count; e++) { 4971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = nai_realm_parse_eap(&r->eap[e], pos, f_end); 4981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos == NULL) 4991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 5001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return f_end; 5031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 5041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct nai_realm * nai_realm_parse(struct wpabuf *anqp, u16 *count) 5071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 5081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm *realm; 5091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *pos, *end; 5101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 i, num; 5111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (anqp == NULL || wpabuf_len(anqp) < 2) 5131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 5141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = wpabuf_head_u8(anqp); 5161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = pos + wpabuf_len(anqp); 5171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt num = WPA_GET_LE16(pos); 5181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "NAI Realm Count: %u", num); 5191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 5201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (num * 5 > end - pos) { 5221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid NAI Realm Count %u - not " 5231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "enough data (%u octets) for that many realms", 5241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt num, (unsigned int) (end - pos)); 5251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 5261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 52861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt realm = os_calloc(num, sizeof(struct nai_realm)); 5291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (realm == NULL) 5301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 5311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < num; i++) { 5331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = nai_realm_parse_realm(&realm[i], pos, end); 5341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos == NULL) { 5351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, num); 5361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 5371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *count = num; 5411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return realm; 5421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 5431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int nai_realm_match(struct nai_realm *realm, const char *home_realm) 5461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 5471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt char *tmp, *pos, *end; 5481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int match = 0; 5491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (realm->realm == NULL || home_realm == NULL) 5511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 5521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_strchr(realm->realm, ';') == NULL) 5541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return os_strcasecmp(realm->realm, home_realm) == 0; 5551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt tmp = os_strdup(realm->realm); 5571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (tmp == NULL) 5581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 5591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = tmp; 5611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (*pos) { 5621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = os_strchr(pos, ';'); 5631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (end) 5641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *end = '\0'; 5651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_strcasecmp(pos, home_realm) == 0) { 5661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt match = 1; 5671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 5681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (end == NULL) 5701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 5711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = end + 1; 5721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(tmp); 5751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return match; 5771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 5781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int nai_realm_cred_username(struct nai_realm_eap *eap) 5811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 5821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap_get_name(EAP_VENDOR_IETF, eap->method) == NULL) 5831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; /* method not supported */ 5841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 585fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (eap->method != EAP_TYPE_TTLS && eap->method != EAP_TYPE_PEAP && 586fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt eap->method != EAP_TYPE_FAST) { 5871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Only tunneled methods with username/password supported */ 5881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 5891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 591fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (eap->method == EAP_TYPE_PEAP || eap->method == EAP_TYPE_FAST) { 592a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (eap->inner_method && 593a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL) 594a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 0; 595a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (!eap->inner_method && 596a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt eap_get_name(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2) == NULL) 597a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 0; 598a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 5991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->method == EAP_TYPE_TTLS) { 6011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->inner_method == 0 && eap->inner_non_eap == 0) 602a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 1; /* Assume TTLS/MSCHAPv2 is used */ 6031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->inner_method && 6041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL) 6051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 6061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->inner_non_eap && 6071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_PAP && 6081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_CHAP && 6091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_MSCHAP && 6101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_MSCHAPV2) 6111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 6121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->inner_method && 6151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_method != EAP_TYPE_GTC && 6161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_method != EAP_TYPE_MSCHAPV2) 6171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 6181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 1; 6201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 6211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 62304949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int nai_realm_cred_cert(struct nai_realm_eap *eap) 62404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 62504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (eap_get_name(EAP_VENDOR_IETF, eap->method) == NULL) 62604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; /* method not supported */ 62704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 62804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (eap->method != EAP_TYPE_TLS) { 62904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Only EAP-TLS supported for credential authentication */ 63004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 63104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 63204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 63304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 1; 63404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 63504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 63604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 63704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic struct nai_realm_eap * nai_realm_find_eap(struct wpa_cred *cred, 6381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm *realm) 6391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 6401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 e; 6411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 64204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred == NULL || 64304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->username == NULL || 64404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->username[0] == '\0' || 64504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ((cred->password == NULL || 64604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->password[0] == '\0') && 64704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (cred->private_key == NULL || 64804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->private_key[0] == '\0'))) 6491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 6501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (e = 0; e < realm->eap_count; e++) { 6521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm_eap *eap = &realm->eap[e]; 65304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->password && cred->password[0] && 65404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt nai_realm_cred_username(eap)) 65504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return eap; 65604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->private_key && cred->private_key[0] && 65704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt nai_realm_cred_cert(eap)) 6581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eap; 6591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 6621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 6631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef INTERWORKING_3GPP 6661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 66704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int plmn_id_match(struct wpabuf *anqp, const char *imsi, int mnc_len) 6681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 66934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 plmn[3], plmn2[3]; 6701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *pos, *end; 6711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 udhl; 6721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 67334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* 67434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * See Annex A of 3GPP TS 24.234 v8.1.0 for description. The network 67534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * operator is allowed to include only two digits of the MNC, so allow 67634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * matches based on both two and three digit MNC assumptions. Since some 67734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * SIM/USIM cards may not expose MNC length conveniently, we may be 67834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * provided the default MNC length 3 here and as such, checking with MNC 67934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * length 2 is justifiable even though 3GPP TS 24.234 does not mention 68034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * that case. Anyway, MCC/MNC pair where both 2 and 3 digit MNC is used 68134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * with otherwise matching values would not be good idea in general, so 68234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * this should not result in selecting incorrect networks. 68334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt */ 68434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* Match with 3 digit MNC */ 6851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt plmn[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4); 68634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt plmn[1] = (imsi[2] - '0') | ((imsi[5] - '0') << 4); 6871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt plmn[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4); 68834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* Match with 2 digit MNC */ 68934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt plmn2[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4); 69034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt plmn2[1] = (imsi[2] - '0') | 0xf0; 69134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt plmn2[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4); 6921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (anqp == NULL) 6941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 6951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = wpabuf_head_u8(anqp); 6961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = pos + wpabuf_len(anqp); 6971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + 2 > end) 6981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 6991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (*pos != 0) { 7001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Unsupported GUD version 0x%x", *pos); 7011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 7021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos++; 7041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt udhl = *pos++; 7051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + udhl > end) { 7061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid UDHL"); 7071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 7081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = pos + udhl; 7101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 71134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Matching against MCC/MNC alternatives: %02x:%02x:%02x or %02x:%02x:%02x (IMSI %s, MNC length %d)", 71234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt plmn[0], plmn[1], plmn[2], plmn2[0], plmn2[1], plmn2[2], 71334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt imsi, mnc_len); 71434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 7151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (pos + 2 <= end) { 7161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 iei, len; 7171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *l_end; 7181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iei = *pos++; 7191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = *pos++ & 0x7f; 7201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + len > end) 7211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 7221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt l_end = pos + len; 7231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (iei == 0 && len > 0) { 7251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* PLMN List */ 7261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 num, i; 72734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "Interworking: PLMN List information element", 72834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos, len); 7291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt num = *pos++; 7301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < num; i++) { 73134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos + 3 > l_end) 7321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 73334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (os_memcmp(pos, plmn, 3) == 0 || 73434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcmp(pos, plmn2, 3) == 0) 7351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 1; /* Found matching PLMN */ 73661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += 3; 7371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 73834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } else { 73934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "Interworking: Unrecognized 3GPP information element", 74034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos, len); 7411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = l_end; 7441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 7471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 7481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int build_root_nai(char *nai, size_t nai_len, const char *imsi, 75161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t mnc_len, char prefix) 7521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 7531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const char *sep, *msin; 75404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char *end, *pos; 7551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t msin_len, plmn_len; 7561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 7581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * TS 23.003, Clause 14 (3GPP to WLAN Interworking) 7591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Root NAI: 7601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * <aka:0|sim:1><IMSI>@wlan.mnc<MNC>.mcc<MCC>.3gppnetwork.org 7611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * <MNC> is zero-padded to three digits in case two-digit MNC is used 7621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 7631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (imsi == NULL || os_strlen(imsi) > 16) { 7651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "No valid IMSI available"); 7661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 7671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sep = os_strchr(imsi, '-'); 76961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sep) { 77061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt plmn_len = sep - imsi; 77161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt msin = sep + 1; 77261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else if (mnc_len && os_strlen(imsi) >= 3 + mnc_len) { 77361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt plmn_len = 3 + mnc_len; 77461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt msin = imsi + plmn_len; 77561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else 7761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 7771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (plmn_len != 5 && plmn_len != 6) 7781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 7791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt msin_len = os_strlen(msin); 7801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = nai; 78204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt end = nai + nai_len; 78304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (prefix) 78404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *pos++ = prefix; 7851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(pos, imsi, plmn_len); 7861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += plmn_len; 7871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(pos, msin, msin_len); 7881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += msin_len; 7891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += os_snprintf(pos, end - pos, "@wlan.mnc"); 7901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (plmn_len == 5) { 7911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = '0'; 7921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = imsi[3]; 7931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = imsi[4]; 7941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 7951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = imsi[3]; 7961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = imsi[4]; 7971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *pos++ = imsi[5]; 7981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 799c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_snprintf(pos, end - pos, ".mcc%c%c%c.3gppnetwork.org", 800c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt imsi[0], imsi[1], imsi[2]); 8011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 80204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 80304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 80404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 80504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 80604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int set_root_nai(struct wpa_ssid *ssid, const char *imsi, char prefix) 80704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 80804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char nai[100]; 80961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (build_root_nai(nai, sizeof(nai), imsi, 0, prefix) < 0) 81004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 8111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return wpa_config_set_quoted(ssid, "identity", nai); 8121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 8131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* INTERWORKING_3GPP */ 8151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8175460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidtstatic int already_connected(struct wpa_supplicant *wpa_s, 8185460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt struct wpa_cred *cred, struct wpa_bss *bss) 8195460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt{ 8204582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt struct wpa_ssid *ssid, *sel_ssid; 8214582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt struct wpa_bss *selected; 8225460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8235460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (wpa_s->wpa_state < WPA_ASSOCIATED || wpa_s->current_ssid == NULL) 8245460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return 0; 8255460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8265460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt ssid = wpa_s->current_ssid; 8275460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (ssid->parent_cred != cred) 8285460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return 0; 8295460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8305460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (ssid->ssid_len != bss->ssid_len || 8315460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) != 0) 8325460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return 0; 8335460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8344582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt sel_ssid = NULL; 8354582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt selected = wpa_supplicant_pick_network(wpa_s, &sel_ssid); 8364582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt if (selected && sel_ssid && sel_ssid->priority > ssid->priority) 8374582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt return 0; /* higher priority network in scan results */ 8384582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt 8395460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return 1; 8405460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt} 8415460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8425460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8435460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidtstatic void remove_duplicate_network(struct wpa_supplicant *wpa_s, 8445460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt struct wpa_cred *cred, 8455460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt struct wpa_bss *bss) 8465460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt{ 8475460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt struct wpa_ssid *ssid; 8485460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8495460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 8505460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (ssid->parent_cred != cred) 8515460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt continue; 8525460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (ssid->ssid_len != bss->ssid_len || 8535460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) != 0) 8545460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt continue; 8555460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8565460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt break; 8575460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt } 8585460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8595460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (ssid == NULL) 8605460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return; 8615460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8625460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Remove duplicate network entry for the same credential"); 8635460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8645460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (ssid == wpa_s->current_ssid) { 8655460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_sm_set_config(wpa_s->wpa, NULL); 8665460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 8675460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_supplicant_deauthenticate(wpa_s, 8685460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt WLAN_REASON_DEAUTH_LEAVING); 8695460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt } 8705460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8715460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpas_notify_network_removed(wpa_s, ssid); 8725460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_config_remove_network(wpa_s->conf, ssid->id); 8735460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt} 8745460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 8755460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 876d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic int interworking_set_hs20_params(struct wpa_supplicant *wpa_s, 877d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpa_ssid *ssid) 87861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 8795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt const char *key_mgmt = NULL; 8805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#ifdef CONFIG_IEEE80211R 8815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt int res; 8825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt struct wpa_driver_capa capa; 8835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 8845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt res = wpa_drv_get_capa(wpa_s, &capa); 8855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (res == 0 && capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) { 8865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt key_mgmt = wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ? 8875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt "WPA-EAP WPA-EAP-SHA256 FT-EAP" : 8885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt "WPA-EAP FT-EAP"; 8895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt } 8905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#endif /* CONFIG_IEEE80211R */ 8915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt 8925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (!key_mgmt) 8935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt key_mgmt = wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ? 8945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt "WPA-EAP WPA-EAP-SHA256" : "WPA-EAP"; 8955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0) 89661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 89761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_config_set(ssid, "proto", "RSN", 0) < 0) 89861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 89961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0) 90061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 90161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 90261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 90361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 90461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 9051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int interworking_connect_3gpp(struct wpa_supplicant *wpa_s, 906f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpa_cred *cred, 9071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_bss *bss) 9081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 9091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef INTERWORKING_3GPP 9101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_ssid *ssid; 9114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int eap_type; 9124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int res; 9134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt char prefix; 9141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 9154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL) 91604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 91704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 9181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR " (3GPP)", 9191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(bss->bssid)); 9201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 9215460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (already_connected(wpa_s, cred, bss)) { 9225460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR, 9235460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt MAC2STR(bss->bssid)); 9245460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return 0; 9255460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt } 9265460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 9275460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt remove_duplicate_network(wpa_s, cred, bss); 9285460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 9291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid = wpa_config_add_network(wpa_s->conf); 9301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ssid == NULL) 9311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 932d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt ssid->parent_cred = cred; 9331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 9341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpas_notify_network_added(wpa_s, ssid); 9351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_config_set_network_defaults(ssid); 93604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ssid->priority = cred->priority; 9371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid->temporary = 1; 9385460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt ssid->ssid = os_zalloc(bss->ssid_len + 1); 9391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ssid->ssid == NULL) 9401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 9415460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len); 9425460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt ssid->ssid_len = bss->ssid_len; 943f9bdef99ce3b2858f2812c745a3d6bb093fb0e5dDmitry Shmidt ssid->eap.sim_num = cred->sim_num; 9441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 945d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (interworking_set_hs20_params(wpa_s, ssid) < 0) 94661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto fail; 94761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 9484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_type = EAP_TYPE_SIM; 9494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->pcsc && wpa_s->scard && scard_supports_umts(wpa_s->scard)) 9504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_type = EAP_TYPE_AKA; 9514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->eap_method && cred->eap_method[0].vendor == EAP_VENDOR_IETF) { 9524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cred->eap_method[0].method == EAP_TYPE_SIM || 9534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt cred->eap_method[0].method == EAP_TYPE_AKA || 9544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt cred->eap_method[0].method == EAP_TYPE_AKA_PRIME) 9554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_type = cred->eap_method[0].method; 9564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 9574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 9584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt switch (eap_type) { 9594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case EAP_TYPE_SIM: 9604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt prefix = '1'; 9614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt res = wpa_config_set(ssid, "eap", "SIM", 0); 9624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt break; 9634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case EAP_TYPE_AKA: 9644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt prefix = '0'; 9654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt res = wpa_config_set(ssid, "eap", "AKA", 0); 9664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt break; 9674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case EAP_TYPE_AKA_PRIME: 9684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt prefix = '6'; 9694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt res = wpa_config_set(ssid, "eap", "AKA'", 0); 9704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt break; 9714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt default: 9724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt res = -1; 9734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt break; 9744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 9754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (res < 0) { 9764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "Selected EAP method (%d) not supported", 9774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_type); 9781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 9791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 9804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 9814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!cred->pcsc && set_root_nai(ssid, cred->imsi, prefix) < 0) { 9821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to set Root NAI"); 9831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 9841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 9851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 98604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->milenage && cred->milenage[0]) { 9871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set_quoted(ssid, "password", 98804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred->milenage) < 0) 9891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 99004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else if (cred->pcsc) { 9911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set_quoted(ssid, "pcsc", "") < 0) 9921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 99304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->conf->pcsc_pin && 99404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_config_set_quoted(ssid, "pin", wpa_s->conf->pcsc_pin) 99504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt < 0) 99604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto fail; 9971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 9981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 999f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->next_ssid = ssid; 100004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_config_update_prio_list(wpa_s->conf); 100104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt interworking_reconnect(wpa_s); 10021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 10041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtfail: 10061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpas_notify_network_removed(wpa_s, ssid); 10071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_config_remove_network(wpa_s->conf, ssid->id); 10081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* INTERWORKING_3GPP */ 10091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 10101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 10111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 10121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 101361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int roaming_consortium_element_match(const u8 *ie, const u8 *rc_id, 101461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t rc_len) 101561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 101661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *pos, *end; 101761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 lens; 101861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 101961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ie == NULL) 102061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 102161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 102261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = ie + 2; 102361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt end = ie + 2 + ie[1]; 102461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 102561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Roaming Consortium element: 102661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Number of ANQP OIs 102761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * OI #1 and #2 lengths 102861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * OI #1, [OI #2], [OI #3] 102961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 103061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 103161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos + 2 > end) 103261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 103361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 103461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos++; /* skip Number of ANQP OIs */ 103561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt lens = *pos++; 103661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos + (lens & 0x0f) + (lens >> 4) > end) 103761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 103861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 103961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if ((lens & 0x0f) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0) 104061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 1; 104161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += lens & 0x0f; 104261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 104361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if ((lens >> 4) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0) 104461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 1; 104561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += lens >> 4; 104661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 104761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos < end && (size_t) (end - pos) == rc_len && 104861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcmp(pos, rc_id, rc_len) == 0) 104961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 1; 105061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 105161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 105261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 105361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 105461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 105561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int roaming_consortium_anqp_match(const struct wpabuf *anqp, 105661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *rc_id, size_t rc_len) 105761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 105861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *pos, *end; 105961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 len; 106061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 106161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (anqp == NULL) 106261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 106361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 106461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = wpabuf_head(anqp); 106561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt end = pos + wpabuf_len(anqp); 106661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 106761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Set of <OI Length, OI> duples */ 106861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt while (pos < end) { 106961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len = *pos++; 107061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos + len > end) 107161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 107261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (len == rc_len && os_memcmp(pos, rc_id, rc_len) == 0) 107361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 1; 107461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += len; 107561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 107661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 107761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 107861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 107961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 108061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 108161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int roaming_consortium_match(const u8 *ie, const struct wpabuf *anqp, 108261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *rc_id, size_t rc_len) 108361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 108461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return roaming_consortium_element_match(ie, rc_id, rc_len) || 108561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt roaming_consortium_anqp_match(anqp, rc_id, rc_len); 108661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 108761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 108861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1089051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic int cred_no_required_oi_match(struct wpa_cred *cred, struct wpa_bss *bss) 1090051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 1091051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt const u8 *ie; 1092051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1093051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (cred->required_roaming_consortium_len == 0) 1094051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 1095051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1096051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM); 1097051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1098051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (ie == NULL && 1099051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL)) 1100051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 1; 1101051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1102051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return !roaming_consortium_match(ie, 1103051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt bss->anqp ? 1104051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt bss->anqp->roaming_consortium : NULL, 1105051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt cred->required_roaming_consortium, 1106051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt cred->required_roaming_consortium_len); 1107051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 1108051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1109051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1110a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic int cred_excluded_ssid(struct wpa_cred *cred, struct wpa_bss *bss) 1111a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{ 1112a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt size_t i; 1113a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1114a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (!cred->excluded_ssid) 1115a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 0; 1116a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1117a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt for (i = 0; i < cred->num_excluded_ssid; i++) { 1118a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt struct excluded_ssid *e = &cred->excluded_ssid[i]; 1119a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (bss->ssid_len == e->ssid_len && 1120a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_memcmp(bss->ssid, e->ssid, e->ssid_len) == 0) 1121a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 1; 1122a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1123a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1124a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 0; 1125a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt} 1126a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1127a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1128f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int cred_below_min_backhaul(struct wpa_supplicant *wpa_s, 1129f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred, struct wpa_bss *bss) 1130f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 1131f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int res; 1132f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt unsigned int dl_bandwidth, ul_bandwidth; 1133f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt const u8 *wan; 1134f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u8 wan_info, dl_load, ul_load; 1135f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u16 lmd; 1136f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u32 ul_speed, dl_speed; 1137f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1138f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!cred->min_dl_bandwidth_home && 1139f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt !cred->min_ul_bandwidth_home && 1140f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt !cred->min_dl_bandwidth_roaming && 1141f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt !cred->min_ul_bandwidth_roaming) 1142f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* No bandwidth constraint specified */ 1143f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1144f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (bss->anqp == NULL || bss->anqp->hs20_wan_metrics == NULL) 1145f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* No WAN Metrics known - ignore constraint */ 1146f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1147f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wan = wpabuf_head(bss->anqp->hs20_wan_metrics); 1148f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wan_info = wan[0]; 1149f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (wan_info & BIT(3)) 1150f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; /* WAN link at capacity */ 1151f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt lmd = WPA_GET_LE16(wan + 11); 1152f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (lmd == 0) 1153f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* Downlink/Uplink Load was not measured */ 1154f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt dl_speed = WPA_GET_LE32(wan + 1); 1155f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ul_speed = WPA_GET_LE32(wan + 5); 1156f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt dl_load = wan[9]; 1157f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ul_load = wan[10]; 1158f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1159f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (dl_speed >= 0xffffff) 1160f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt dl_bandwidth = dl_speed / 255 * (255 - dl_load); 1161f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt else 1162f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt dl_bandwidth = dl_speed * (255 - dl_load) / 255; 1163f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1164f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (ul_speed >= 0xffffff) 1165f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ul_bandwidth = ul_speed / 255 * (255 - ul_load); 1166f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt else 1167f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ul_bandwidth = ul_speed * (255 - ul_load) / 255; 1168f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1169f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt res = interworking_home_sp_cred(wpa_s, cred, bss->anqp ? 1170f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bss->anqp->domain_name : NULL); 1171f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (res > 0) { 1172f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred->min_dl_bandwidth_home > dl_bandwidth) 1173f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 1174f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred->min_ul_bandwidth_home > ul_bandwidth) 1175f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 1176f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 1177f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred->min_dl_bandwidth_roaming > dl_bandwidth) 1178f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 1179f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred->min_ul_bandwidth_roaming > ul_bandwidth) 1180f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 1181f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1182f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1183f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; 1184f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 1185f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1186f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1187f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int cred_over_max_bss_load(struct wpa_supplicant *wpa_s, 1188f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred, struct wpa_bss *bss) 1189f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 1190f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt const u8 *ie; 1191f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int res; 1192f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1193f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!cred->max_bss_load) 1194f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* No BSS Load constraint specified */ 1195f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1196f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_BSS_LOAD); 1197f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (ie == NULL || ie[1] < 3) 1198f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* No BSS Load advertised */ 1199f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1200f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt res = interworking_home_sp_cred(wpa_s, cred, bss->anqp ? 1201f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bss->anqp->domain_name : NULL); 1202f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (res <= 0) 1203f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* Not a home network */ 1204f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1205f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return ie[4] > cred->max_bss_load; 1206f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 1207f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1208f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1209f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int has_proto_match(const u8 *pos, const u8 *end, u8 proto) 1210f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 1211f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt while (pos + 4 <= end) { 1212f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (pos[0] == proto && pos[3] == 1 /* Open */) 1213f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 1214f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt pos += 4; 1215f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1216f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1217f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; 1218f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 1219f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1220f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1221f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int has_proto_port_match(const u8 *pos, const u8 *end, u8 proto, 1222f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u16 port) 1223f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 1224f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt while (pos + 4 <= end) { 1225f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (pos[0] == proto && WPA_GET_LE16(&pos[1]) == port && 1226f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt pos[3] == 1 /* Open */) 1227f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 1228f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt pos += 4; 1229f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1230f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1231f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; 1232f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 1233f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1234f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1235f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int cred_conn_capab_missing(struct wpa_supplicant *wpa_s, 1236f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred, struct wpa_bss *bss) 1237f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 1238f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int res; 1239f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt const u8 *capab, *end; 1240f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt unsigned int i, j; 1241f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int *ports; 1242f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1243f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!cred->num_req_conn_capab) 1244f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* No connection capability constraint specified */ 1245f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1246f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (bss->anqp == NULL || bss->anqp->hs20_connection_capability == NULL) 1247f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* No Connection Capability known - ignore constraint 1248f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt */ 1249f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1250f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt res = interworking_home_sp_cred(wpa_s, cred, bss->anqp ? 1251f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bss->anqp->domain_name : NULL); 1252f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (res > 0) 1253f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* No constraint in home network */ 1254f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1255f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt capab = wpabuf_head(bss->anqp->hs20_connection_capability); 1256f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt end = capab + wpabuf_len(bss->anqp->hs20_connection_capability); 1257f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1258f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (i = 0; i < cred->num_req_conn_capab; i++) { 1259f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ports = cred->req_conn_capab_port[i]; 1260f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ports) { 1261f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!has_proto_match(capab, end, 1262f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->req_conn_capab_proto[i])) 1263f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 1264f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 1265f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (j = 0; ports[j] > -1; j++) { 1266f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!has_proto_port_match( 1267f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt capab, end, 1268f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->req_conn_capab_proto[i], 1269f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ports[j])) 1270f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 1271f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1272f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1273f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1274f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1275f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; 1276f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 1277f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1278f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 127961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic struct wpa_cred * interworking_credentials_available_roaming_consortium( 1280f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 1281f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int *excluded) 128261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 128361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_cred *cred, *selected = NULL; 128461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *ie; 1285f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int is_excluded = 0; 128661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 128761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM); 128861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 12894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ie == NULL && 12904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL)) 129161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return NULL; 129261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 129361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_s->conf->cred == NULL) 129461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return NULL; 129561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 129661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 129761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->roaming_consortium_len == 0) 129861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt continue; 129961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 13004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!roaming_consortium_match(ie, 13014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss->anqp ? 13024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss->anqp->roaming_consortium : 13034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt NULL, 130461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->roaming_consortium, 130561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->roaming_consortium_len)) 130661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt continue; 130761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1308051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (cred_no_required_oi_match(cred, bss)) 1309051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt continue; 1310f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && cred_below_min_backhaul(wpa_s, cred, bss)) 1311f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1312f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && cred_over_max_bss_load(wpa_s, cred, bss)) 1313f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1314f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && cred_conn_capab_missing(wpa_s, cred, bss)) 1315f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1316f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred_excluded_ssid(cred, bss)) { 1317f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded == NULL) 1318f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1319f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected == NULL) { 1320f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = cred; 1321f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt is_excluded = 1; 1322f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1323f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 1324f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected == NULL || is_excluded || 1325f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_prio_cmp(selected, cred) < 0) { 1326f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = cred; 1327f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt is_excluded = 0; 1328f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1329f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 133061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 133161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1332f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded) 1333f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt *excluded = is_excluded; 1334f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 133561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return selected; 133661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 133761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 133861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 133961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int interworking_set_eap_params(struct wpa_ssid *ssid, 134061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_cred *cred, int ttls) 134161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 134261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->eap_method) { 134361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ttls = cred->eap_method->vendor == EAP_VENDOR_IETF && 134461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->eap_method->method == EAP_TYPE_TTLS; 134561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 134661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(ssid->eap.eap_methods); 134761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->eap.eap_methods = 134861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_malloc(sizeof(struct eap_method_type) * 2); 134961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ssid->eap.eap_methods == NULL) 135061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 135161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(ssid->eap.eap_methods, cred->eap_method, 135261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sizeof(*cred->eap_method)); 135361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->eap.eap_methods[1].vendor = EAP_VENDOR_IETF; 135461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->eap.eap_methods[1].method = EAP_TYPE_NONE; 135561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 135661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 135761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ttls && cred->username && cred->username[0]) { 135861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const char *pos; 135961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt char *anon; 136061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Use anonymous NAI in Phase 1 */ 136161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = os_strchr(cred->username, '@'); 136261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos) { 136361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t buflen = 9 + os_strlen(pos) + 1; 136461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anon = os_malloc(buflen); 136561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (anon == NULL) 136661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 136761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_snprintf(anon, buflen, "anonymous%s", pos); 136861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else if (cred->realm) { 136961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t buflen = 10 + os_strlen(cred->realm) + 1; 137061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anon = os_malloc(buflen); 137161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (anon == NULL) 137261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 137361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_snprintf(anon, buflen, "anonymous@%s", cred->realm); 137461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else { 137561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt anon = os_strdup("anonymous"); 137661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (anon == NULL) 137761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 137861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 137961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_config_set_quoted(ssid, "anonymous_identity", anon) < 138061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 0) { 138161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(anon); 138261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 138361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 138461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(anon); 138561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 138661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 138761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->username && cred->username[0] && 138861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "identity", cred->username) < 0) 138961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 139061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 139161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->password && cred->password[0]) { 139261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->ext_password && 139361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set(ssid, "password", cred->password, 0) < 0) 139461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 139561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!cred->ext_password && 139661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "password", cred->password) < 139761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 0) 139861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 139961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 140061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 140161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->client_cert && cred->client_cert[0] && 140261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "client_cert", cred->client_cert) < 0) 140361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 140461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1405d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#ifdef ANDROID 1406d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (cred->private_key && 1407d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt os_strncmp(cred->private_key, "keystore://", 11) == 0) { 1408d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt /* Use OpenSSL engine configuration for Android keystore */ 1409d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (wpa_config_set_quoted(ssid, "engine_id", "keystore") < 0 || 1410d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_config_set_quoted(ssid, "key_id", 1411d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt cred->private_key + 11) < 0 || 1412d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_config_set(ssid, "engine", "1", 0) < 0) 1413d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return -1; 1414d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } else 1415d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#endif /* ANDROID */ 141661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->private_key && cred->private_key[0] && 141761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "private_key", cred->private_key) < 0) 141861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 141961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 142061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->private_key_passwd && cred->private_key_passwd[0] && 142161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "private_key_passwd", 142261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->private_key_passwd) < 0) 142361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 142461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 142561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->phase1) { 142661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(ssid->eap.phase1); 142761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->eap.phase1 = os_strdup(cred->phase1); 142861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 142961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->phase2) { 143061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_free(ssid->eap.phase2); 143161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->eap.phase2 = os_strdup(cred->phase2); 143261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 143361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 143461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->ca_cert && cred->ca_cert[0] && 143561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_quoted(ssid, "ca_cert", cred->ca_cert) < 0) 143661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 143761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1438051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (cred->domain_suffix_match && cred->domain_suffix_match[0] && 1439051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_config_set_quoted(ssid, "domain_suffix_match", 1440051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt cred->domain_suffix_match) < 0) 1441051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return -1; 1442051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1443f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ssid->eap.ocsp = cred->ocsp; 1444f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 144561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 144661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 144761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 144861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 144961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int interworking_connect_roaming_consortium( 145061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_cred *cred, 14515460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt struct wpa_bss *bss) 145261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 145361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_ssid *ssid; 145461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 145561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR " based on " 145661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "roaming consortium match", MAC2STR(bss->bssid)); 145761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 14585460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (already_connected(wpa_s, cred, bss)) { 14595460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR, 14605460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt MAC2STR(bss->bssid)); 14615460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return 0; 14625460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt } 14635460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 14645460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt remove_duplicate_network(wpa_s, cred, bss); 14655460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 146661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid = wpa_config_add_network(wpa_s->conf); 146761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ssid == NULL) 146861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 1469d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt ssid->parent_cred = cred; 147061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpas_notify_network_added(wpa_s, ssid); 147161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_set_network_defaults(ssid); 147261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->priority = cred->priority; 147361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid->temporary = 1; 14745460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt ssid->ssid = os_zalloc(bss->ssid_len + 1); 147561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (ssid->ssid == NULL) 147661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto fail; 14775460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len); 14785460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt ssid->ssid_len = bss->ssid_len; 147961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1480d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (interworking_set_hs20_params(wpa_s, ssid) < 0) 148161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto fail; 148261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 148361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (cred->eap_method == NULL) { 148461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: No EAP method set for " 148561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "credential using roaming consortium"); 148661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto fail; 148761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 148861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 148961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (interworking_set_eap_params( 149061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ssid, cred, 149161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->eap_method->vendor == EAP_VENDOR_IETF && 149261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred->eap_method->method == EAP_TYPE_TTLS) < 0) 149361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto fail; 149461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1495f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->next_ssid = ssid; 149661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_update_prio_list(wpa_s->conf); 149761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt interworking_reconnect(wpa_s); 149861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 149961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 150061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 150161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtfail: 150261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpas_notify_network_removed(wpa_s, ssid); 150361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_config_remove_network(wpa_s->conf, ssid->id); 150461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 150561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 150661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 150761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1508f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int interworking_connect_helper(struct wpa_supplicant *wpa_s, 1509f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_bss *bss, int allow_excluded) 15101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1511f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpa_cred *cred, *cred_rc, *cred_3gpp; 15121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_ssid *ssid; 15131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm *realm; 15141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm_eap *eap = NULL; 15151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 count, i; 15161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt char buf[100]; 1517f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int excluded = 0, *excl = allow_excluded ? &excluded : NULL; 151809f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt const char *name; 15191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 152004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->conf->cred == NULL || bss == NULL) 15211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 15225460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (disallowed_bssid(wpa_s, bss->bssid) || 15235460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) { 15245460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Reject connection to disallowed BSS " 15251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 15261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 15271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 15281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1529f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Considering BSS " MACSTR 1530f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt " for connection (allow_excluded=%d)", 1531f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MAC2STR(bss->bssid), allow_excluded); 1532f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 153361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) { 153461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 153561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * We currently support only HS 2.0 networks and those are 153661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * required to use WPA2-Enterprise. 153761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 153861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Network does not use " 153961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "RSN"); 154061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 154161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 154261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1543f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_rc = interworking_credentials_available_roaming_consortium( 1544f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s, bss, 0, excl); 1545f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (cred_rc) { 1546f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Highest roaming " 1547f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "consortium matching credential priority %d " 1548f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "sp_priority %d", 1549f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_rc->priority, cred_rc->sp_priority); 1550f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (allow_excluded && excl && !(*excl)) 1551f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excl = NULL; 1552f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1553f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1554f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred = interworking_credentials_available_realm(wpa_s, bss, 0, excl); 1555f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (cred) { 1556f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Highest NAI Realm list " 1557f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "matching credential priority %d sp_priority %d", 1558f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->priority, cred->sp_priority); 1559f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (allow_excluded && excl && !(*excl)) 1560f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excl = NULL; 1561f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1562f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1563f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_3gpp = interworking_credentials_available_3gpp(wpa_s, bss, 0, 1564f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excl); 1565f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (cred_3gpp) { 1566f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Highest 3GPP matching " 1567f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "credential priority %d sp_priority %d", 1568f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_3gpp->priority, cred_3gpp->sp_priority); 1569f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (allow_excluded && excl && !(*excl)) 1570f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excl = NULL; 1571f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1572f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1573f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!cred_rc && !cred && !cred_3gpp) { 1574f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: No full credential matches - consider options without BW(etc.) limits"); 1575f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_rc = interworking_credentials_available_roaming_consortium( 1576f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s, bss, 1, excl); 1577f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred_rc) { 1578f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Highest roaming " 1579f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "consortium matching credential priority %d " 1580f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "sp_priority %d (ignore BW)", 1581f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_rc->priority, cred_rc->sp_priority); 1582f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (allow_excluded && excl && !(*excl)) 1583f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excl = NULL; 1584f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1585f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1586f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred = interworking_credentials_available_realm(wpa_s, bss, 1, 1587f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excl); 1588f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred) { 1589f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Highest NAI Realm " 1590f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "list matching credential priority %d " 1591f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "sp_priority %d (ignore BW)", 1592f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->priority, cred->sp_priority); 1593f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (allow_excluded && excl && !(*excl)) 1594f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excl = NULL; 1595f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1596f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1597f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_3gpp = interworking_credentials_available_3gpp(wpa_s, bss, 1598f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1, excl); 1599f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred_3gpp) { 1600f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Highest 3GPP " 1601f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "matching credential priority %d " 1602f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "sp_priority %d (ignore BW)", 1603f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_3gpp->priority, cred_3gpp->sp_priority); 1604f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (allow_excluded && excl && !(*excl)) 1605f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excl = NULL; 1606f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1607f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1608f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1609f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (cred_rc && 1610f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (cred == NULL || cred_prio_cmp(cred_rc, cred) >= 0) && 1611f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (cred_3gpp == NULL || cred_prio_cmp(cred_rc, cred_3gpp) >= 0)) 1612f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return interworking_connect_roaming_consortium(wpa_s, cred_rc, 16135460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt bss); 161461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1615f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (cred_3gpp && 1616f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (cred == NULL || cred_prio_cmp(cred_3gpp, cred) >= 0)) { 1617f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return interworking_connect_3gpp(wpa_s, cred_3gpp, bss); 1618f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1619f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1620f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (cred == NULL) { 1621f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: No matching credentials " 1622f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt "found for " MACSTR, MAC2STR(bss->bssid)); 1623f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return -1; 1624f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1625f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 16264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt realm = nai_realm_parse(bss->anqp ? bss->anqp->nai_realm : NULL, 16274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt &count); 16281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (realm == NULL) { 16291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Could not parse NAI " 16301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Realm list from " MACSTR, MAC2STR(bss->bssid)); 1631f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return -1; 16321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 16331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1634f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt for (i = 0; i < count; i++) { 1635f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (!nai_realm_match(&realm[i], cred->realm)) 1636f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt continue; 1637f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt eap = nai_realm_find_eap(cred, &realm[i]); 16381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap) 16391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 16401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 16411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!eap) { 16431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: No matching credentials " 16441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "and EAP method found for " MACSTR, 16451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(bss->bssid)); 16461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, count); 16471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 16481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 16491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR, 16511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(bss->bssid)); 16521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16535460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (already_connected(wpa_s, cred, bss)) { 16545460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR, 16555460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt MAC2STR(bss->bssid)); 16565460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt nai_realm_free(realm, count); 16575460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return 0; 16585460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt } 16595460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 16605460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt remove_duplicate_network(wpa_s, cred, bss); 16615460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 16621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid = wpa_config_add_network(wpa_s->conf); 16631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ssid == NULL) { 16641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, count); 16651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 16661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1667d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt ssid->parent_cred = cred; 16681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpas_notify_network_added(wpa_s, ssid); 16691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_config_set_network_defaults(ssid); 167004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ssid->priority = cred->priority; 16711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid->temporary = 1; 16725460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt ssid->ssid = os_zalloc(bss->ssid_len + 1); 16731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ssid->ssid == NULL) 16741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 16755460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len); 16765460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt ssid->ssid_len = bss->ssid_len; 16771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1678d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (interworking_set_hs20_params(wpa_s, ssid) < 0) 167904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto fail; 168004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 168161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_config_set(ssid, "eap", eap_get_name(EAP_VENDOR_IETF, 168261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt eap->method), 0) < 0) 16831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 16841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (eap->method) { 16861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case EAP_TYPE_TTLS: 16871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap->inner_method) { 16881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_snprintf(buf, sizeof(buf), "\"autheap=%s\"", 16891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_get_name(EAP_VENDOR_IETF, 16901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap->inner_method)); 16911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set(ssid, "phase2", buf, 0) < 0) 16921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 16931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 16941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 16951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (eap->inner_non_eap) { 16961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_PAP: 16971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set(ssid, "phase2", "\"auth=PAP\"", 0) < 16981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 0) 16991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 17001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 17011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_CHAP: 17021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set(ssid, "phase2", "\"auth=CHAP\"", 0) 17031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt < 0) 17041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 17051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 17061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_MSCHAP: 1707c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAP\"", 1708c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 0) < 0) 17091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 17101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 17111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NAI_REALM_INNER_NON_EAP_MSCHAPV2: 17121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAPV2\"", 17131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 0) < 0) 17141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 17151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 1716a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt default: 1717a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt /* EAP params were not set - assume TTLS/MSCHAPv2 */ 1718a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAPV2\"", 1719a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 0) < 0) 1720a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt goto fail; 1721a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt break; 17221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 17231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 17241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case EAP_TYPE_PEAP: 1725fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case EAP_TYPE_FAST: 1726fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (wpa_config_set(ssid, "phase1", "\"fast_provisioning=2\"", 1727fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 0) < 0) 1728fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt goto fail; 1729fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (wpa_config_set(ssid, "pac_file", 1730fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt "\"blob://pac_interworking\"", 0) < 0) 1731fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt goto fail; 173209f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt name = eap_get_name(EAP_VENDOR_IETF, 173309f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt eap->inner_method ? eap->inner_method : 173409f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt EAP_TYPE_MSCHAPV2); 173509f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt if (name == NULL) 173609f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt goto fail; 173709f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt os_snprintf(buf, sizeof(buf), "\"auth=%s\"", name); 17381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_config_set(ssid, "phase2", buf, 0) < 0) 17391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 17401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 174104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case EAP_TYPE_TLS: 174204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 17431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 17441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 174561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (interworking_set_eap_params(ssid, cred, 174661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt eap->method == EAP_TYPE_TTLS) < 0) 17471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 17481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, count); 17501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1751f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->next_ssid = ssid; 175204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_config_update_prio_list(wpa_s->conf); 175304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt interworking_reconnect(wpa_s); 17541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 17561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtfail: 17581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpas_notify_network_removed(wpa_s, ssid); 17591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_config_remove_network(wpa_s->conf, ssid->id); 17601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, count); 17611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 17621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 17631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1765f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtint interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) 1766f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 1767f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return interworking_connect_helper(wpa_s, bss, 1); 1768f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 1769f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1770f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1771df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#ifdef PCSC_FUNCS 1772df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidtstatic int interworking_pcsc_read_imsi(struct wpa_supplicant *wpa_s) 1773df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt{ 1774df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt size_t len; 1775df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 1776df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (wpa_s->imsi[0] && wpa_s->mnc_len) 1777df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return 0; 1778df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 1779df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt len = sizeof(wpa_s->imsi) - 1; 1780df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) { 1781df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt scard_deinit(wpa_s->scard); 1782df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_s->scard = NULL; 1783df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI"); 1784df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 1785df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 1786df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_s->imsi[len] = '\0'; 1787df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard); 1788df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)", 1789df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_s->imsi, wpa_s->mnc_len); 1790df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 1791df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return 0; 1792df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt} 1793df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#endif /* PCSC_FUNCS */ 1794df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 1795df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 179604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic struct wpa_cred * interworking_credentials_available_3gpp( 1797f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 1798f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int *excluded) 17991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 18002f3b8dec59373945c5feef8a78ced8967a80cc66Dmitry Shmidt struct wpa_cred *selected = NULL; 18012f3b8dec59373945c5feef8a78ced8967a80cc66Dmitry Shmidt#ifdef INTERWORKING_3GPP 18022f3b8dec59373945c5feef8a78ced8967a80cc66Dmitry Shmidt struct wpa_cred *cred; 180304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int ret; 1804f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int is_excluded = 0; 18051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 18064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL) 180704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 18081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1809b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt#ifdef CONFIG_EAP_PROXY 1810b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt if (!wpa_s->imsi[0]) { 1811b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt size_t len; 1812b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: IMSI not available - try to read again through eap_proxy"); 1813b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, 1814b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt wpa_s->imsi, 1815b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt &len); 1816b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt if (wpa_s->mnc_len > 0) { 1817b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt wpa_s->imsi[len] = '\0'; 1818b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)", 1819b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt wpa_s->imsi, wpa_s->mnc_len); 1820b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt } else { 1821b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available"); 1822b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt } 1823b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt } 1824b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt#endif /* CONFIG_EAP_PROXY */ 1825b96dad47218788efffa3db0fe7f1b54a7d19e366Dmitry Shmidt 182604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 182704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char *sep; 182804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const char *imsi; 182904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int mnc_len; 183034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt char imsi_buf[16]; 183134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t msin_len; 183204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 183304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef PCSC_FUNCS 1834df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (cred->pcsc && wpa_s->scard) { 1835df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (interworking_pcsc_read_imsi(wpa_s) < 0) 1836df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt continue; 183704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt imsi = wpa_s->imsi; 183804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt mnc_len = wpa_s->mnc_len; 183904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto compare; 184004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 184104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* PCSC_FUNCS */ 184234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#ifdef CONFIG_EAP_PROXY 184334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (cred->pcsc && wpa_s->mnc_len > 0 && wpa_s->imsi[0]) { 184434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt imsi = wpa_s->imsi; 184534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt mnc_len = wpa_s->mnc_len; 184634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt goto compare; 184734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 184834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* CONFIG_EAP_PROXY */ 18491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 185004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->imsi == NULL || !cred->imsi[0] || 1851051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt (!wpa_s->conf->external_sim && 1852051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt (cred->milenage == NULL || !cred->milenage[0]))) 185304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 185404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 185504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sep = os_strchr(cred->imsi, '-'); 185604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (sep == NULL || 185704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (sep - cred->imsi != 5 && sep - cred->imsi != 6)) 185804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 185904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt mnc_len = sep - cred->imsi - 3; 186034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(imsi_buf, cred->imsi, 3 + mnc_len); 186134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt sep++; 186234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt msin_len = os_strlen(cred->imsi); 186334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (3 + mnc_len + msin_len >= sizeof(imsi_buf) - 1) 186434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt msin_len = sizeof(imsi_buf) - 3 - mnc_len - 1; 186534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(&imsi_buf[3 + mnc_len], sep, msin_len); 186634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt imsi_buf[3 + mnc_len + msin_len] = '\0'; 186734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt imsi = imsi_buf; 186834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 186934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#if defined(PCSC_FUNCS) || defined(CONFIG_EAP_PROXY) 187004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt compare: 187134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* PCSC_FUNCS || CONFIG_EAP_PROXY */ 187204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Parsing 3GPP info from " 187304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 18744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt ret = plmn_id_match(bss->anqp->anqp_3gpp, imsi, mnc_len); 187504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "PLMN match %sfound", ret ? "" : "not "); 187604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (ret) { 1877051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (cred_no_required_oi_match(cred, bss)) 1878051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt continue; 1879f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && 1880f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_below_min_backhaul(wpa_s, cred, bss)) 1881f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1882f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && 1883f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_over_max_bss_load(wpa_s, cred, bss)) 1884f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1885f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && 1886f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_conn_capab_missing(wpa_s, cred, bss)) 1887f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1888f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred_excluded_ssid(cred, bss)) { 1889f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded == NULL) 1890f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1891f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected == NULL) { 1892f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = cred; 1893f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt is_excluded = 1; 1894f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1895f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 1896f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected == NULL || is_excluded || 1897f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_prio_cmp(selected, cred) < 0) { 1898f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = cred; 1899f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt is_excluded = 0; 1900f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1901f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 190204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 190304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 1904f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1905f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded) 1906f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt *excluded = is_excluded; 19071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* INTERWORKING_3GPP */ 190804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return selected; 19091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 19101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 191204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic struct wpa_cred * interworking_credentials_available_realm( 1913f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 1914f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int *excluded) 19151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 191604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_cred *cred, *selected = NULL; 19171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nai_realm *realm; 19181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 count, i; 1919f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int is_excluded = 0; 19201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp == NULL || bss->anqp->nai_realm == NULL) 192204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 19231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 192404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->conf->cred == NULL) 192504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 19261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Parsing NAI Realm list from " 19281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 19294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt realm = nai_realm_parse(bss->anqp->nai_realm, &count); 19301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (realm == NULL) { 19311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Could not parse NAI " 19321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Realm list from " MACSTR, MAC2STR(bss->bssid)); 193304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 19341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 19351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 193604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 193704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cred->realm == NULL) 19381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt continue; 193904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 194004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0; i < count; i++) { 194104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!nai_realm_match(&realm[i], cred->realm)) 194204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 194304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (nai_realm_find_eap(cred, &realm[i])) { 1944051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (cred_no_required_oi_match(cred, bss)) 1945051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt continue; 1946f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && 1947f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_below_min_backhaul(wpa_s, cred, bss)) 1948f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1949f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && 1950f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_over_max_bss_load(wpa_s, cred, bss)) 1951f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1952f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!ignore_bw && 1953f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_conn_capab_missing(wpa_s, cred, bss)) 1954f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1955f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred_excluded_ssid(cred, bss)) { 1956f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded == NULL) 1957f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1958f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected == NULL) { 1959f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = cred; 1960f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt is_excluded = 1; 1961f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1962f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 1963f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected == NULL || is_excluded || 1964f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_prio_cmp(selected, cred) < 0) 1965f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt { 1966f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = cred; 1967f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt is_excluded = 0; 1968f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1969f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 197004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 197104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 19721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 19731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 19741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nai_realm_free(realm, count); 19761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1977f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded) 1978f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt *excluded = is_excluded; 1979f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 198004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return selected; 198104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 198204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 198304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 1984f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic struct wpa_cred * interworking_credentials_available_helper( 1985f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw, 1986f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int *excluded) 198704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 198804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_cred *cred, *cred2; 1989f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int excluded1, excluded2; 199004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 19915460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (disallowed_bssid(wpa_s, bss->bssid) || 19925460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) { 19935460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Ignore disallowed BSS " 19945460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 19955460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return NULL; 19965460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt } 19975460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 1998f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred = interworking_credentials_available_realm(wpa_s, bss, ignore_bw, 1999f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt &excluded1); 2000f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred2 = interworking_credentials_available_3gpp(wpa_s, bss, ignore_bw, 2001f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt &excluded2); 2002f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred && cred2 && 2003f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (cred_prio_cmp(cred2, cred) >= 0 || (!excluded2 && excluded1))) { 200404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred = cred2; 2005f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excluded1 = excluded2; 2006f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2007f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!cred) { 200804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cred = cred2; 2009f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excluded1 = excluded2; 2010f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 201104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2012f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred2 = interworking_credentials_available_roaming_consortium( 2013f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s, bss, ignore_bw, &excluded2); 2014f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred && cred2 && 2015f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (cred_prio_cmp(cred2, cred) >= 0 || (!excluded2 && excluded1))) { 201661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred = cred2; 2017f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excluded1 = excluded2; 2018f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2019f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!cred) { 202061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt cred = cred2; 2021f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excluded1 = excluded2; 2022f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 202361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2024f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded) 2025f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt *excluded = excluded1; 202604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return cred; 20271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 20281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 20291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2030f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic struct wpa_cred * interworking_credentials_available( 2031f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int *excluded) 2032f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 2033f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred; 2034f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2035f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded) 2036f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt *excluded = 0; 2037f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred = interworking_credentials_available_helper(wpa_s, bss, 0, 2038f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excluded); 2039f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (cred) 2040f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return cred; 2041f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return interworking_credentials_available_helper(wpa_s, bss, 1, 2042f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excluded); 2043f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 2044f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2045f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2046f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtint domain_name_list_contains(struct wpabuf *domain_names, 2047f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt const char *domain, int exact_match) 20481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 204904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *pos, *end; 205004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt size_t len; 205104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 205204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt len = os_strlen(domain); 205304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos = wpabuf_head(domain_names); 205404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt end = pos + wpabuf_len(domain_names); 205504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 205604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt while (pos + 1 < end) { 205704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (pos + 1 + pos[0] > end) 205804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 205904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 206004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "Interworking: AP domain name", 206104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos + 1, pos[0]); 206204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (pos[0] == len && 206304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_strncasecmp(domain, (const char *) (pos + 1), len) == 0) 206404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 1; 2065f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!exact_match && pos[0] > len && pos[pos[0] - len] == '.') { 2066f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt const char *ap = (const char *) (pos + 1); 2067f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int offset = pos[0] - len; 2068f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (os_strncasecmp(domain, ap + offset, len) == 0) 2069f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 2070f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 207104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 207204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += 1 + pos[0]; 207304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 207404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 207504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 207604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 207704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 207804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2079d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtint interworking_home_sp_cred(struct wpa_supplicant *wpa_s, 2080d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpa_cred *cred, 2081d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpabuf *domain_names) 208204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 2083051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt size_t i; 208468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt int ret = -1; 208504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef INTERWORKING_3GPP 208604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char nai[100], *realm; 208704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2088d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt char *imsi = NULL; 2089d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt int mnc_len = 0; 2090d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (cred->imsi) 2091d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt imsi = cred->imsi; 2092df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#ifdef PCSC_FUNCS 2093df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt else if (cred->pcsc && wpa_s->scard) { 2094df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (interworking_pcsc_read_imsi(wpa_s) < 0) 2095df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 2096d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt imsi = wpa_s->imsi; 2097d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt mnc_len = wpa_s->mnc_len; 2098d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 2099df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#endif /* PCSC_FUNCS */ 2100051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#ifdef CONFIG_EAP_PROXY 2101051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt else if (cred->pcsc && wpa_s->mnc_len > 0 && wpa_s->imsi[0]) { 2102051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt imsi = wpa_s->imsi; 2103051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt mnc_len = wpa_s->mnc_len; 2104051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 2105051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#endif /* CONFIG_EAP_PROXY */ 2106a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (domain_names && 2107a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt imsi && build_root_nai(nai, sizeof(nai), imsi, mnc_len, 0) == 0) { 2108d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt realm = os_strchr(nai, '@'); 2109d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (realm) 2110d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt realm++; 2111d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Search for match " 2112d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt "with SIM/USIM domain %s", realm); 2113d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (realm && 2114f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt domain_name_list_contains(domain_names, realm, 1)) 2115d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 1; 211668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (realm) 211768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt ret = 0; 2118d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 211904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* INTERWORKING_3GPP */ 212004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2121a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (domain_names == NULL || cred->domain == NULL) 212268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return ret; 212304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2124051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt for (i = 0; i < cred->num_domain; i++) { 2125051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Search for match with " 2126051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt "home SP FQDN %s", cred->domain[i]); 2127f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (domain_name_list_contains(domain_names, cred->domain[i], 1)) 2128051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 1; 2129051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 2130d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 2131d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 0; 2132d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt} 2133d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 2134d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 2135d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic int interworking_home_sp(struct wpa_supplicant *wpa_s, 2136d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpabuf *domain_names) 2137d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{ 2138d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpa_cred *cred; 2139d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 2140d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (domain_names == NULL || wpa_s->conf->cred == NULL) 2141d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return -1; 2142d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 2143d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 2144d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt int res = interworking_home_sp_cred(wpa_s, cred, domain_names); 2145d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (res) 2146d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return res; 214704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 214804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 214904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 215004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 215104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 215204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 215304949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int interworking_find_network_match(struct wpa_supplicant *wpa_s) 215404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 215504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_bss *bss; 215604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_ssid *ssid; 215704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 215804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 215904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 216004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpas_network_disabled(wpa_s, ssid) || 216104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ssid->mode != WPAS_MODE_INFRA) 216204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 216304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (ssid->ssid_len != bss->ssid_len || 216404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) != 216504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 0) 216604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 216704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 216804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * TODO: Consider more accurate matching of security 216904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * configuration similarly to what is done in events.c 217004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 217104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 1; 217204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 217304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 217404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 217504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 21761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 21771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 21781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2179f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int roaming_partner_match(struct wpa_supplicant *wpa_s, 2180f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct roaming_partner *partner, 2181f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpabuf *domain_names) 2182f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 2183f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Comparing roaming_partner info fqdn='%s' exact_match=%d priority=%u country='%s'", 2184f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt partner->fqdn, partner->exact_match, partner->priority, 2185f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt partner->country); 2186f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "Interworking: Domain names", 2187f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_head(domain_names), 2188f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_len(domain_names)); 2189f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!domain_name_list_contains(domain_names, partner->fqdn, 2190f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt partner->exact_match)) 2191f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; 2192f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* TODO: match Country */ 2193f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 1; 2194f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 2195f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2196f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2197f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic u8 roaming_prio(struct wpa_supplicant *wpa_s, struct wpa_cred *cred, 2198f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_bss *bss) 2199f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 2200f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt size_t i; 2201f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2202f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (bss->anqp == NULL || bss->anqp->domain_name == NULL) { 2203f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: No ANQP domain name info -> use default roaming partner priority 128"); 2204f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 128; /* cannot check preference with domain name */ 2205f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2206f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2207f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (interworking_home_sp_cred(wpa_s, cred, bss->anqp->domain_name) > 0) 2208f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt { 2209f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Determined to be home SP -> use maximum preference 0 as roaming partner priority"); 2210f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 0; /* max preference for home SP network */ 2211f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2212f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2213f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (i = 0; i < cred->num_roaming_partner; i++) { 2214f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (roaming_partner_match(wpa_s, &cred->roaming_partner[i], 2215f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bss->anqp->domain_name)) { 2216f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Roaming partner preference match - priority %u", 2217f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->roaming_partner[i].priority); 2218f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return cred->roaming_partner[i].priority; 2219f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2220f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2221f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2222f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: No roaming partner preference match - use default roaming partner priority 128"); 2223f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return 128; 2224f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 2225f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2226f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2227f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic struct wpa_bss * pick_best_roaming_partner(struct wpa_supplicant *wpa_s, 2228f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_bss *selected, 2229f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred) 2230f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 2231f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_bss *bss; 2232f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u8 best_prio, prio; 2233f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred2; 2234f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2235f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* 2236f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt * Check if any other BSS is operated by a more preferred roaming 2237f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt * partner. 2238f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt */ 2239f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2240f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt best_prio = roaming_prio(wpa_s, cred, selected); 2241f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: roaming_prio=%u for selected BSS " 2242f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MACSTR " (cred=%d)", best_prio, MAC2STR(selected->bssid), 2243f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->id); 2244f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2245f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 2246f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (bss == selected) 2247f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 2248f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred2 = interworking_credentials_available(wpa_s, bss, NULL); 2249f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!cred2) 2250f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 2251f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) 2252f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 2253f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt prio = roaming_prio(wpa_s, cred2, bss); 2254f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: roaming_prio=%u for BSS " 2255f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MACSTR " (cred=%d)", prio, MAC2STR(bss->bssid), 2256f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred2->id); 2257f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (prio < best_prio) { 2258f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int bh1, bh2, load1, load2, conn1, conn2; 2259f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bh1 = cred_below_min_backhaul(wpa_s, cred, selected); 2260f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt load1 = cred_over_max_bss_load(wpa_s, cred, selected); 2261f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt conn1 = cred_conn_capab_missing(wpa_s, cred, selected); 2262f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bh2 = cred_below_min_backhaul(wpa_s, cred2, bss); 2263f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt load2 = cred_over_max_bss_load(wpa_s, cred2, bss); 2264f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt conn2 = cred_conn_capab_missing(wpa_s, cred2, bss); 2265f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: old: %d %d %d new: %d %d %d", 2266f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bh1, load1, conn1, bh2, load2, conn2); 2267f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (bh1 || load1 || conn1 || !(bh2 || load2 || conn2)) { 2268f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Better roaming partner " MACSTR " selected", MAC2STR(bss->bssid)); 2269f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt best_prio = prio; 2270f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = bss; 2271f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2272f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2273f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2274f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2275f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return selected; 2276f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 2277f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2278f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 22791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_select_network(struct wpa_supplicant *wpa_s) 22801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 228104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_bss *bss, *selected = NULL, *selected_home = NULL; 2282f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_bss *selected2 = NULL, *selected2_home = NULL; 22831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt unsigned int count = 0; 228404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const char *type; 228504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int res; 2286f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *cred, *selected_cred = NULL; 2287f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *selected_home_cred = NULL; 2288f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *selected2_cred = NULL; 2289f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct wpa_cred *selected2_home_cred = NULL; 22901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 22911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->network_select = 0; 22921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2293f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Select network (auto_select=%d)", 2294f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->auto_select); 22951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 2296f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int excluded = 0; 2297f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int bh, bss_load, conn_capab; 2298f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred = interworking_credentials_available(wpa_s, bss, 2299f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt &excluded); 230004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!cred) 23011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt continue; 230261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) { 230361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 230461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * We currently support only HS 2.0 networks and those 230561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * are required to use WPA2-Enterprise. 230661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 230761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Credential match " 230861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "with " MACSTR " but network does not use " 230961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "RSN", MAC2STR(bss->bssid)); 231061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt continue; 231161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 2312f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!excluded) 2313f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt count++; 23144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt res = interworking_home_sp(wpa_s, bss->anqp ? 23154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss->anqp->domain_name : NULL); 231604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (res > 0) 231704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt type = "home"; 231804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt else if (res == 0) 231904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt type = "roaming"; 232004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt else 232104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt type = "unknown"; 2322f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bh = cred_below_min_backhaul(wpa_s, cred, bss); 2323f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bss_load = cred_over_max_bss_load(wpa_s, cred, bss); 2324f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt conn_capab = cred_conn_capab_missing(wpa_s, cred, bss); 2325f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "%s" MACSTR " type=%s%s%s%s id=%d priority=%d sp_priority=%d", 2326f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt excluded ? INTERWORKING_BLACKLISTED : INTERWORKING_AP, 2327f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MAC2STR(bss->bssid), type, 2328f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bh ? " below_min_backhaul=1" : "", 2329f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt bss_load ? " over_max_bss_load=1" : "", 2330f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt conn_capab ? " conn_capab_missing=1" : "", 2331f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred->id, cred->priority, cred->sp_priority); 2332f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (excluded) 2333f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 233461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_s->auto_select || 233561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt (wpa_s->conf->auto_interworking && 233661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_s->auto_network_select)) { 2337f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (bh || bss_load || conn_capab) { 2338f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected2_cred == NULL || 2339f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_prio_cmp(cred, selected2_cred) > 0) { 2340f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Mark as selected2"); 2341f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected2 = bss; 2342f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected2_cred = cred; 2343f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2344f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (res > 0 && 2345f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (selected2_home_cred == NULL || 2346f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_prio_cmp(cred, selected2_home_cred) > 2347f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 0)) { 2348f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Mark as selected2_home"); 2349f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected2_home = bss; 2350f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected2_home_cred = cred; 2351f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2352f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 2353f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected_cred == NULL || 2354f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_prio_cmp(cred, selected_cred) > 0) { 2355f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Mark as selected"); 2356f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = bss; 2357f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected_cred = cred; 2358f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2359f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (res > 0 && 2360f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (selected_home_cred == NULL || 2361f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_prio_cmp(cred, selected_home_cred) > 2362f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 0)) { 2363f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Mark as selected_home"); 2364f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected_home = bss; 2365f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected_home_cred = cred; 2366f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 236704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 236804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 236904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 237004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 237104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (selected_home && selected_home != selected && 2372f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected_home_cred && 2373f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (selected_cred == NULL || 2374f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt cred_prio_cmp(selected_home_cred, selected_cred) >= 0)) { 237504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Prefer network operated by the Home SP */ 2376f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Overrided selected with selected_home"); 237704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt selected = selected_home; 2378f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected_cred = selected_home_cred; 2379f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2380f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2381f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!selected) { 2382f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected2_home) { 2383f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Use home BSS with BW limit mismatch since no other network could be selected"); 2384f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = selected2_home; 2385f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected_cred = selected2_home_cred; 2386f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else if (selected2) { 2387f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Use visited BSS with BW limit mismatch since no other network could be selected"); 2388f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = selected2; 2389f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected_cred = selected2_cred; 2390f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 23911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 23921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 23931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (count == 0) { 239404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 239504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * No matching network was found based on configured 239604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * credentials. Check whether any of the enabled network blocks 239704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * have matching APs. 239804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 239904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (interworking_find_network_match(wpa_s)) { 240004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Possible BSS " 240104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "match for enabled network configurations"); 2402717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (wpa_s->auto_select) { 240361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt interworking_reconnect(wpa_s); 2404717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt return; 2405717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt } 240661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 240761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 240861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpa_s->auto_network_select) { 240961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Continue " 241061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "scanning after ANQP fetch"); 241161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_supplicant_req_scan(wpa_s, wpa_s->scan_interval, 241261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 0); 241304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 241404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 241504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 24161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, INTERWORKING_NO_MATCH "No network " 24171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "with matching credentials found"); 24181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 24191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2420f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (selected) { 2421f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Selected " MACSTR, 2422f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MAC2STR(selected->bssid)); 2423f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected = pick_best_roaming_partner(wpa_s, selected, 2424f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt selected_cred); 2425f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Selected " MACSTR 2426f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt " (after best roaming partner selection)", 2427f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MAC2STR(selected->bssid)); 2428f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, INTERWORKING_SELECTED MACSTR, 2429f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MAC2STR(selected->bssid)); 24301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_connect(wpa_s, selected); 2431f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 24321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 24331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic struct wpa_bss_anqp * 24364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtinterworking_match_anqp_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) 24374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 24384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_bss *other; 24394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 24404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (is_zero_ether_addr(bss->hessid)) 24414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return NULL; /* Cannot be in the same homegenous ESS */ 24424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 24434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt dl_list_for_each(other, &wpa_s->bss, struct wpa_bss, list) { 24444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (other == bss) 24454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 24464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (other->anqp == NULL) 24474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 2448a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (other->anqp->roaming_consortium == NULL && 2449a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt other->anqp->nai_realm == NULL && 2450a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt other->anqp->anqp_3gpp == NULL && 2451a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt other->anqp->domain_name == NULL) 2452a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt continue; 24534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!(other->flags & WPA_BSS_ANQP_FETCH_TRIED)) 24544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 24554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (os_memcmp(bss->hessid, other->hessid, ETH_ALEN) != 0) 24564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 24574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->ssid_len != other->ssid_len || 24584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_memcmp(bss->ssid, other->ssid, bss->ssid_len) != 0) 24594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 24604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 24614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Share ANQP data with " 24624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "already fetched BSSID " MACSTR " and " MACSTR, 24634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt MAC2STR(other->bssid), MAC2STR(bss->bssid)); 24644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt other->anqp->users++; 24654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return other->anqp; 24664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 24674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 24684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return NULL; 24694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 24704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 24714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 24721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s) 24731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 24741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_bss *bss; 24751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int found = 0; 24761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *ie; 24771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2478f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: next_anqp_fetch - " 2479f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "fetch_anqp_in_progress=%d fetch_osu_icon_in_progress=%d", 2480f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->fetch_anqp_in_progress, 2481f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->fetch_osu_icon_in_progress); 2482f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2483f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (eloop_terminated() || !wpa_s->fetch_anqp_in_progress) { 2484f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Stop next-ANQP-fetch"); 2485f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return; 2486f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2487f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2488f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (wpa_s->fetch_osu_icon_in_progress) { 2489f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Next icon (in progress)"); 2490f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt hs20_next_osu_icon(wpa_s); 24911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 2492f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 24931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 24951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!(bss->caps & IEEE80211_CAP_ESS)) 24961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt continue; 24971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB); 24981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ie == NULL || ie[1] < 4 || !(ie[5] & 0x80)) 24991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt continue; /* AP does not support Interworking */ 25005460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (disallowed_bssid(wpa_s, bss->bssid) || 25015460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) 25025460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt continue; /* Disallowed BSS */ 25031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!(bss->flags & WPA_BSS_ANQP_FETCH_TRIED)) { 25054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp == NULL) { 25064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss->anqp = interworking_match_anqp_info(wpa_s, 25074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss); 25084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp) { 25094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Shared data already fetched */ 25104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt continue; 25114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 25124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt bss->anqp = wpa_bss_anqp_alloc(); 25134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss->anqp == NULL) 25144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt break; 25154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 25161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt found++; 25171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bss->flags |= WPA_BSS_ANQP_FETCH_TRIED; 25181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "Starting ANQP fetch for " 25191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(bss->bssid)); 25201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_anqp_send_req(wpa_s, bss); 25211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 25221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 25231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 25241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (found == 0) { 2526f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (wpa_s->fetch_osu_info) { 2527f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (wpa_s->num_prov_found == 0 && 2528f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->num_osu_scans < 3) { 2529f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "HS 2.0: No OSU providers seen - try to scan again"); 2530f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt hs20_start_osu_scan(wpa_s); 2531f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return; 2532f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2533f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Next icon"); 2534f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt hs20_osu_icon_fetch(wpa_s); 2535f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return; 2536f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 25371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "ANQP fetch completed"); 25381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->fetch_anqp_in_progress = 0; 25391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->network_select) 25401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_select_network(wpa_s); 25411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 25421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 25431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 254561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid interworking_start_fetch_anqp(struct wpa_supplicant *wpa_s) 25461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 25471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_bss *bss; 25481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) 25501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bss->flags &= ~WPA_BSS_ANQP_FETCH_TRIED; 25511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->fetch_anqp_in_progress = 1; 25531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_next_anqp_fetch(wpa_s); 25541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 25551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint interworking_fetch_anqp(struct wpa_supplicant *wpa_s) 25581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 25591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) 25601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 25611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->network_select = 0; 25634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_s->fetch_all_anqp = 1; 2564f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->fetch_osu_info = 0; 25651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_start_fetch_anqp(wpa_s); 25671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 25691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 25701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s) 25731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 25741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!wpa_s->fetch_anqp_in_progress) 25751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 25761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->fetch_anqp_in_progress = 0; 25781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 25791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, 258215907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt u16 info_ids[], size_t num_ids, u32 subtypes) 25831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 25841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf; 258515907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt struct wpabuf *hs20_buf = NULL; 25861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret = 0; 25871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int freq; 25881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_bss *bss; 25891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int res; 25901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt freq = wpa_s->assoc_freq; 25921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bss = wpa_bss_get_bssid(wpa_s, dst); 2593d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (bss) { 2594d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_bss_anqp_unshare_alloc(bss); 25951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt freq = bss->freq; 2596d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 25971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (freq <= 0) 25981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 25991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Query Request to " MACSTR " for %u id(s)", 26011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(dst), (unsigned int) num_ids); 26021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 260315907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt#ifdef CONFIG_HS20 260415907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt if (subtypes != 0) { 260515907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt hs20_buf = wpabuf_alloc(100); 260615907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt if (hs20_buf == NULL) 260715907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt return -1; 260815907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt hs20_put_anqp_req(subtypes, NULL, 0, hs20_buf); 260915907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt } 261015907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt#endif /* CONFIG_HS20 */ 261115907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt 261215907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt buf = anqp_build_req(info_ids, num_ids, hs20_buf); 261315907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt wpabuf_free(hs20_buf); 26141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL) 26151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 26161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s); 26181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (res < 0) { 26191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request"); 2620051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpabuf_free(buf); 26211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = -1; 26221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else 26231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token " 26241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "%u", res); 26251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ret; 26271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 26281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, 2631444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt struct wpa_bss *bss, const u8 *sa, 2632444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt u16 info_id, 26331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *data, size_t slen) 26341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 26351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *pos = data; 26364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct wpa_bss_anqp *anqp = NULL; 263704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_HS20 263804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 type; 263904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_HS20 */ 26401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (bss) 26424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp = bss->anqp; 26434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 26441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (info_id) { 26451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_CAPABILITY_LIST: 26461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 26471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " ANQP Capability list", MAC2STR(sa)); 26481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 26491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_VENUE_NAME: 26501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 26511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " Venue Name", MAC2STR(sa)); 26521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Venue Name", pos, slen); 26534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 26544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->venue_name); 26554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->venue_name = wpabuf_alloc_copy(pos, slen); 26561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 26571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 26581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_NETWORK_AUTH_TYPE: 26591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 26601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " Network Authentication Type information", 26611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(sa)); 26621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Network Authentication " 26631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Type", pos, slen); 26644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 26654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->network_auth_type); 26664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->network_auth_type = wpabuf_alloc_copy(pos, slen); 26671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 26681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 26691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_ROAMING_CONSORTIUM: 26701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 26711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " Roaming Consortium list", MAC2STR(sa)); 26721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Roaming Consortium", 26731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos, slen); 26744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 26754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->roaming_consortium); 26764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->roaming_consortium = wpabuf_alloc_copy(pos, slen); 26771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 26781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 26791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_IP_ADDR_TYPE_AVAILABILITY: 26801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 26811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " IP Address Type Availability information", 26821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(sa)); 26831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "ANQP: IP Address Availability", 26841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos, slen); 26854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 26864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->ip_addr_type_availability); 26874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->ip_addr_type_availability = 26881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_alloc_copy(pos, slen); 26891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 26901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 26911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_NAI_REALM: 26921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 26931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " NAI Realm list", MAC2STR(sa)); 26941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "ANQP: NAI Realm", pos, slen); 26954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 26964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->nai_realm); 26974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->nai_realm = wpabuf_alloc_copy(pos, slen); 26981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 26991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 27001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_3GPP_CELLULAR_NETWORK: 27011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 27021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " 3GPP Cellular Network information", MAC2STR(sa)); 27031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "ANQP: 3GPP Cellular Network", 27041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos, slen); 27054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 27064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->anqp_3gpp); 27074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->anqp_3gpp = wpabuf_alloc_copy(pos, slen); 27081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 27091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 27101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_DOMAIN_NAME: 27111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR 27121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " Domain Name list", MAC2STR(sa)); 27131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: Domain Name", pos, slen); 27144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (anqp) { 27154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpabuf_free(anqp->domain_name); 27164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt anqp->domain_name = wpabuf_alloc_copy(pos, slen); 27171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 27181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 27191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case ANQP_VENDOR_SPECIFIC: 27201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (slen < 3) 27211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 27221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 27231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (WPA_GET_BE24(pos)) { 272404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_HS20 272504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case OUI_WFA: 272604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos += 3; 272704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt slen -= 3; 272804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 272904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (slen < 1) 273004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 273104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt type = *pos++; 273204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt slen--; 273304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 273404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt switch (type) { 273504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case HS20_ANQP_OUI_TYPE: 273604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hs20_parse_rx_hs20_anqp_resp(wpa_s, sa, pos, 273704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt slen); 273804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 273904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt default: 274004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "HS20: Unsupported ANQP " 274104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "vendor type %u", type); 274204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 274304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 274404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 274504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_HS20 */ 27461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt default: 27471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Unsupported " 27481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "vendor-specific ANQP OUI %06x", 27491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_GET_BE24(pos)); 27501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 27511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 27521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 27531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt default: 27541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Unsupported ANQP Info ID " 27551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "%u", info_id); 27561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 27571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 27581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 27591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 27601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 27611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token, 27621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt enum gas_query_result result, 27631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct wpabuf *adv_proto, 27641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct wpabuf *resp, u16 status_code) 27651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 27661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_supplicant *wpa_s = ctx; 27671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *pos; 27681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *end; 27691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 info_id; 27701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 slen; 2771444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt struct wpa_bss *bss = NULL, *tmp; 27721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2773f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: anqp_resp_cb dst=" MACSTR 2774f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt " dialog_token=%u result=%d status_code=%u", 2775f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MAC2STR(dst), dialog_token, result, status_code); 2776f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (result != GAS_QUERY_SUCCESS) { 2777f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (wpa_s->fetch_osu_icon_in_progress) 2778f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt hs20_icon_fetch_failed(wpa_s); 27791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 2780f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 27811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 27821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = wpabuf_head(adv_proto); 27831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpabuf_len(adv_proto) < 4 || pos[0] != WLAN_EID_ADV_PROTO || 27841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos[1] < 2 || pos[3] != ACCESS_NETWORK_QUERY_PROTOCOL) { 27851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Unexpected Advertisement " 27861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Protocol in response"); 2787f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (wpa_s->fetch_osu_icon_in_progress) 2788f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt hs20_icon_fetch_failed(wpa_s); 27891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 27901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 27911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2792444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt /* 2793444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt * If possible, select the BSS entry based on which BSS entry was used 2794444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt * for the request. This can help in cases where multiple BSS entries 2795444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt * may exist for the same AP. 2796444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt */ 2797444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt dl_list_for_each_reverse(tmp, &wpa_s->bss, struct wpa_bss, list) { 2798444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (tmp == wpa_s->interworking_gas_bss && 2799444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt os_memcmp(tmp->bssid, dst, ETH_ALEN) == 0) { 2800444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt bss = tmp; 2801444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt break; 2802444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 2803444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 2804444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (bss == NULL) 2805444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt bss = wpa_bss_get_bssid(wpa_s, dst); 2806444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt 28071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = wpabuf_head(resp); 28081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = pos + wpabuf_len(resp); 28091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 28101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (pos < end) { 28111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + 4 > end) { 28121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Invalid element"); 28131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 28141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 28151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt info_id = WPA_GET_LE16(pos); 28161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 28171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt slen = WPA_GET_LE16(pos); 28181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 28191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + slen > end) { 28201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "ANQP: Invalid element length " 28211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "for Info ID %u", info_id); 28221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 28231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2824444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt interworking_parse_rx_anqp_resp(wpa_s, bss, dst, info_id, pos, 28251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt slen); 28261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += slen; 28271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2828f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2829f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt hs20_notify_parse_done(wpa_s); 28301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 28311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 28321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 28331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void interworking_scan_res_handler(struct wpa_supplicant *wpa_s, 28341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_scan_results *scan_res) 28351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 28361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Scan results available - start " 28371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "ANQP fetch"); 28381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_start_fetch_anqp(wpa_s); 28391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 28401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 28411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2842fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtint interworking_select(struct wpa_supplicant *wpa_s, int auto_select, 2843fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt int *freqs) 28441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 28451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt interworking_stop_fetch_anqp(wpa_s); 28461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->network_select = 1; 284761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_s->auto_network_select = 0; 28481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->auto_select = !!auto_select; 28494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_s->fetch_all_anqp = 0; 2850f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_s->fetch_osu_info = 0; 28511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "Interworking: Start scan for network " 28521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "selection"); 28531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->scan_res_handler = interworking_scan_res_handler; 285468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_s->normal_scans = 0; 2855d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_s->scan_req = MANUAL_SCAN_REQ; 2856fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_free(wpa_s->manual_scan_freqs); 2857fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->manual_scan_freqs = freqs; 285868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_s->after_wps = 0; 285968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_s->known_wps_freq = 0; 28601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_req_scan(wpa_s, 0, 0); 28611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 28621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 28631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 286461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 286561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 286661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, 286761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt enum gas_query_result result, 286861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const struct wpabuf *adv_proto, 286961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const struct wpabuf *resp, u16 status_code) 287061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 287161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_supplicant *wpa_s = ctx; 2872fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpabuf *n; 287361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 287461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, GAS_RESPONSE_INFO "addr=" MACSTR 287561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt " dialog_token=%d status_code=%d resp_len=%d", 287661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt MAC2STR(addr), dialog_token, status_code, 287761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt resp ? (int) wpabuf_len(resp) : -1); 287861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!resp) 287961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 288061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2881fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt n = wpabuf_dup(resp); 2882fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (n == NULL) 288361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 2884fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpabuf_free(wpa_s->prev_gas_resp); 2885fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->prev_gas_resp = wpa_s->last_gas_resp; 2886fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_memcpy(wpa_s->prev_gas_addr, wpa_s->last_gas_addr, ETH_ALEN); 2887fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->prev_gas_dialog_token = wpa_s->last_gas_dialog_token; 2888fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->last_gas_resp = n; 288961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(wpa_s->last_gas_addr, addr, ETH_ALEN); 289061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_s->last_gas_dialog_token = dialog_token; 289161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 289261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 289361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 289461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst, 289561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const struct wpabuf *adv_proto, 289661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const struct wpabuf *query) 289761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 289861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *buf; 289961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int ret = 0; 290061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int freq; 290161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpa_bss *bss; 290261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int res; 290361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t len; 29047f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt u8 query_resp_len_limit = 0; 290561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 290661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt freq = wpa_s->assoc_freq; 290761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt bss = wpa_bss_get_bssid(wpa_s, dst); 290861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (bss) 290961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt freq = bss->freq; 291061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (freq <= 0) 291161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 291261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 291361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "GAS request to " MACSTR " (freq %d MHz)", 291461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt MAC2STR(dst), freq); 291561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "Advertisement Protocol ID", adv_proto); 291661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "GAS Query", query); 291761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 291861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len = 3 + wpabuf_len(adv_proto) + 2; 291961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (query) 292061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len += wpabuf_len(query); 292161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt buf = gas_build_initial_req(0, len); 292261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (buf == NULL) 292361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 292461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 292561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Advertisement Protocol IE */ 292661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO); 292761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_u8(buf, 1 + wpabuf_len(adv_proto)); /* Length */ 29287f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt wpabuf_put_u8(buf, query_resp_len_limit & 0x7f); 292961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(buf, adv_proto); 293061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 293161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* GAS Query */ 293261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (query) { 293361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, wpabuf_len(query)); 293461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_buf(buf, query); 293561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else 293661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_put_le16(buf, 0); 293761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 293861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt res = gas_query_req(wpa_s->gas, dst, freq, buf, gas_resp_cb, wpa_s); 293961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (res < 0) { 294061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "GAS: Failed to send Query Request"); 2941051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpabuf_free(buf); 294261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ret = -1; 294361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else 294461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "GAS: Query started with dialog token " 294561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "%u", res); 294661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 294761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return ret; 294861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 2949