1e28a4053SRui Paulo /* 2e28a4053SRui Paulo * hostapd / IEEE 802.1X-2004 Authenticator 3f05cddf9SRui Paulo * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> 4e28a4053SRui Paulo * 5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6f05cddf9SRui Paulo * See README for more details. 7e28a4053SRui Paulo */ 8e28a4053SRui Paulo 9e28a4053SRui Paulo #include "utils/includes.h" 10e28a4053SRui Paulo 11e28a4053SRui Paulo #include "utils/common.h" 12e28a4053SRui Paulo #include "utils/eloop.h" 13e28a4053SRui Paulo #include "crypto/md5.h" 14e28a4053SRui Paulo #include "crypto/crypto.h" 15f05cddf9SRui Paulo #include "crypto/random.h" 16e28a4053SRui Paulo #include "common/ieee802_11_defs.h" 17e28a4053SRui Paulo #include "radius/radius.h" 18e28a4053SRui Paulo #include "radius/radius_client.h" 19e28a4053SRui Paulo #include "eap_server/eap.h" 20e28a4053SRui Paulo #include "eap_common/eap_wsc_common.h" 21e28a4053SRui Paulo #include "eapol_auth/eapol_auth_sm.h" 22e28a4053SRui Paulo #include "eapol_auth/eapol_auth_sm_i.h" 23f05cddf9SRui Paulo #include "p2p/p2p.h" 24e28a4053SRui Paulo #include "hostapd.h" 25e28a4053SRui Paulo #include "accounting.h" 26e28a4053SRui Paulo #include "sta_info.h" 27e28a4053SRui Paulo #include "wpa_auth.h" 28e28a4053SRui Paulo #include "preauth_auth.h" 29e28a4053SRui Paulo #include "pmksa_cache_auth.h" 30e28a4053SRui Paulo #include "ap_config.h" 31f05cddf9SRui Paulo #include "ap_drv_ops.h" 325b9c547cSRui Paulo #include "wps_hostapd.h" 335b9c547cSRui Paulo #include "hs20.h" 34e28a4053SRui Paulo #include "ieee802_1x.h" 35e28a4053SRui Paulo 36e28a4053SRui Paulo 37e28a4053SRui Paulo static void ieee802_1x_finished(struct hostapd_data *hapd, 385b9c547cSRui Paulo struct sta_info *sta, int success, 395b9c547cSRui Paulo int remediation); 40e28a4053SRui Paulo 41e28a4053SRui Paulo 42e28a4053SRui Paulo static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta, 43e28a4053SRui Paulo u8 type, const u8 *data, size_t datalen) 44e28a4053SRui Paulo { 45e28a4053SRui Paulo u8 *buf; 46e28a4053SRui Paulo struct ieee802_1x_hdr *xhdr; 47e28a4053SRui Paulo size_t len; 48e28a4053SRui Paulo int encrypt = 0; 49e28a4053SRui Paulo 50e28a4053SRui Paulo len = sizeof(*xhdr) + datalen; 51e28a4053SRui Paulo buf = os_zalloc(len); 52e28a4053SRui Paulo if (buf == NULL) { 53e28a4053SRui Paulo wpa_printf(MSG_ERROR, "malloc() failed for " 54e28a4053SRui Paulo "ieee802_1x_send(len=%lu)", 55e28a4053SRui Paulo (unsigned long) len); 56e28a4053SRui Paulo return; 57e28a4053SRui Paulo } 58e28a4053SRui Paulo 59e28a4053SRui Paulo xhdr = (struct ieee802_1x_hdr *) buf; 60e28a4053SRui Paulo xhdr->version = hapd->conf->eapol_version; 61e28a4053SRui Paulo xhdr->type = type; 62e28a4053SRui Paulo xhdr->length = host_to_be16(datalen); 63e28a4053SRui Paulo 64e28a4053SRui Paulo if (datalen > 0 && data != NULL) 65e28a4053SRui Paulo os_memcpy(xhdr + 1, data, datalen); 66e28a4053SRui Paulo 67e28a4053SRui Paulo if (wpa_auth_pairwise_set(sta->wpa_sm)) 68e28a4053SRui Paulo encrypt = 1; 695b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS 705b9c547cSRui Paulo if (hapd->ext_eapol_frame_io) { 715b9c547cSRui Paulo size_t hex_len = 2 * len + 1; 725b9c547cSRui Paulo char *hex = os_malloc(hex_len); 735b9c547cSRui Paulo 745b9c547cSRui Paulo if (hex) { 755b9c547cSRui Paulo wpa_snprintf_hex(hex, hex_len, buf, len); 765b9c547cSRui Paulo wpa_msg(hapd->msg_ctx, MSG_INFO, 775b9c547cSRui Paulo "EAPOL-TX " MACSTR " %s", 785b9c547cSRui Paulo MAC2STR(sta->addr), hex); 795b9c547cSRui Paulo os_free(hex); 805b9c547cSRui Paulo } 815b9c547cSRui Paulo } else 825b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */ 83e28a4053SRui Paulo if (sta->flags & WLAN_STA_PREAUTH) { 84e28a4053SRui Paulo rsn_preauth_send(hapd, sta, buf, len); 85e28a4053SRui Paulo } else { 86f05cddf9SRui Paulo hostapd_drv_hapd_send_eapol( 87f05cddf9SRui Paulo hapd, sta->addr, buf, len, 88f05cddf9SRui Paulo encrypt, hostapd_sta_flags_to_drv(sta->flags)); 89e28a4053SRui Paulo } 90e28a4053SRui Paulo 91e28a4053SRui Paulo os_free(buf); 92e28a4053SRui Paulo } 93e28a4053SRui Paulo 94e28a4053SRui Paulo 95e28a4053SRui Paulo void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd, 96e28a4053SRui Paulo struct sta_info *sta, int authorized) 97e28a4053SRui Paulo { 98e28a4053SRui Paulo int res; 99e28a4053SRui Paulo 100e28a4053SRui Paulo if (sta->flags & WLAN_STA_PREAUTH) 101e28a4053SRui Paulo return; 102e28a4053SRui Paulo 103e28a4053SRui Paulo if (authorized) { 104f05cddf9SRui Paulo ap_sta_set_authorized(hapd, sta, 1); 105f05cddf9SRui Paulo res = hostapd_set_authorized(hapd, sta, 1); 106e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 107e28a4053SRui Paulo HOSTAPD_LEVEL_DEBUG, "authorizing port"); 108e28a4053SRui Paulo } else { 109f05cddf9SRui Paulo ap_sta_set_authorized(hapd, sta, 0); 110f05cddf9SRui Paulo res = hostapd_set_authorized(hapd, sta, 0); 111e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 112e28a4053SRui Paulo HOSTAPD_LEVEL_DEBUG, "unauthorizing port"); 113e28a4053SRui Paulo } 114e28a4053SRui Paulo 115e28a4053SRui Paulo if (res && errno != ENOENT) { 1165b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "Could not set station " MACSTR 1175b9c547cSRui Paulo " flags for kernel driver (errno=%d).", 1185b9c547cSRui Paulo MAC2STR(sta->addr), errno); 119e28a4053SRui Paulo } 120e28a4053SRui Paulo 121f05cddf9SRui Paulo if (authorized) { 1225b9c547cSRui Paulo os_get_reltime(&sta->connected_time); 123e28a4053SRui Paulo accounting_sta_start(hapd, sta); 124e28a4053SRui Paulo } 125f05cddf9SRui Paulo } 126e28a4053SRui Paulo 127e28a4053SRui Paulo 128*325151a3SRui Paulo #ifndef CONFIG_FIPS 129*325151a3SRui Paulo #ifndef CONFIG_NO_RC4 130*325151a3SRui Paulo 131e28a4053SRui Paulo static void ieee802_1x_tx_key_one(struct hostapd_data *hapd, 132e28a4053SRui Paulo struct sta_info *sta, 133e28a4053SRui Paulo int idx, int broadcast, 134e28a4053SRui Paulo u8 *key_data, size_t key_len) 135e28a4053SRui Paulo { 136e28a4053SRui Paulo u8 *buf, *ekey; 137e28a4053SRui Paulo struct ieee802_1x_hdr *hdr; 138e28a4053SRui Paulo struct ieee802_1x_eapol_key *key; 139e28a4053SRui Paulo size_t len, ekey_len; 140e28a4053SRui Paulo struct eapol_state_machine *sm = sta->eapol_sm; 141e28a4053SRui Paulo 142e28a4053SRui Paulo if (sm == NULL) 143e28a4053SRui Paulo return; 144e28a4053SRui Paulo 145e28a4053SRui Paulo len = sizeof(*key) + key_len; 146e28a4053SRui Paulo buf = os_zalloc(sizeof(*hdr) + len); 147e28a4053SRui Paulo if (buf == NULL) 148e28a4053SRui Paulo return; 149e28a4053SRui Paulo 150e28a4053SRui Paulo hdr = (struct ieee802_1x_hdr *) buf; 151e28a4053SRui Paulo key = (struct ieee802_1x_eapol_key *) (hdr + 1); 152e28a4053SRui Paulo key->type = EAPOL_KEY_TYPE_RC4; 153f05cddf9SRui Paulo WPA_PUT_BE16(key->key_length, key_len); 154e28a4053SRui Paulo wpa_get_ntp_timestamp(key->replay_counter); 155e28a4053SRui Paulo 156f05cddf9SRui Paulo if (random_get_bytes(key->key_iv, sizeof(key->key_iv))) { 157e28a4053SRui Paulo wpa_printf(MSG_ERROR, "Could not get random numbers"); 158e28a4053SRui Paulo os_free(buf); 159e28a4053SRui Paulo return; 160e28a4053SRui Paulo } 161e28a4053SRui Paulo 162e28a4053SRui Paulo key->key_index = idx | (broadcast ? 0 : BIT(7)); 163e28a4053SRui Paulo if (hapd->conf->eapol_key_index_workaround) { 164e28a4053SRui Paulo /* According to some information, WinXP Supplicant seems to 165e28a4053SRui Paulo * interpret bit7 as an indication whether the key is to be 166e28a4053SRui Paulo * activated, so make it possible to enable workaround that 167e28a4053SRui Paulo * sets this bit for all keys. */ 168e28a4053SRui Paulo key->key_index |= BIT(7); 169e28a4053SRui Paulo } 170e28a4053SRui Paulo 171e28a4053SRui Paulo /* Key is encrypted using "Key-IV + MSK[0..31]" as the RC4-key and 172e28a4053SRui Paulo * MSK[32..63] is used to sign the message. */ 173e28a4053SRui Paulo if (sm->eap_if->eapKeyData == NULL || sm->eap_if->eapKeyDataLen < 64) { 174e28a4053SRui Paulo wpa_printf(MSG_ERROR, "No eapKeyData available for encrypting " 175e28a4053SRui Paulo "and signing EAPOL-Key"); 176e28a4053SRui Paulo os_free(buf); 177e28a4053SRui Paulo return; 178e28a4053SRui Paulo } 179e28a4053SRui Paulo os_memcpy((u8 *) (key + 1), key_data, key_len); 180e28a4053SRui Paulo ekey_len = sizeof(key->key_iv) + 32; 181e28a4053SRui Paulo ekey = os_malloc(ekey_len); 182e28a4053SRui Paulo if (ekey == NULL) { 183e28a4053SRui Paulo wpa_printf(MSG_ERROR, "Could not encrypt key"); 184e28a4053SRui Paulo os_free(buf); 185e28a4053SRui Paulo return; 186e28a4053SRui Paulo } 187e28a4053SRui Paulo os_memcpy(ekey, key->key_iv, sizeof(key->key_iv)); 188e28a4053SRui Paulo os_memcpy(ekey + sizeof(key->key_iv), sm->eap_if->eapKeyData, 32); 189e28a4053SRui Paulo rc4_skip(ekey, ekey_len, 0, (u8 *) (key + 1), key_len); 190e28a4053SRui Paulo os_free(ekey); 191e28a4053SRui Paulo 192e28a4053SRui Paulo /* This header is needed here for HMAC-MD5, but it will be regenerated 193e28a4053SRui Paulo * in ieee802_1x_send() */ 194e28a4053SRui Paulo hdr->version = hapd->conf->eapol_version; 195e28a4053SRui Paulo hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; 196e28a4053SRui Paulo hdr->length = host_to_be16(len); 197e28a4053SRui Paulo hmac_md5(sm->eap_if->eapKeyData + 32, 32, buf, sizeof(*hdr) + len, 198e28a4053SRui Paulo key->key_signature); 199e28a4053SRui Paulo 200e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "IEEE 802.1X: Sending EAPOL-Key to " MACSTR 201e28a4053SRui Paulo " (%s index=%d)", MAC2STR(sm->addr), 202e28a4053SRui Paulo broadcast ? "broadcast" : "unicast", idx); 203e28a4053SRui Paulo ieee802_1x_send(hapd, sta, IEEE802_1X_TYPE_EAPOL_KEY, (u8 *) key, len); 204e28a4053SRui Paulo if (sta->eapol_sm) 205e28a4053SRui Paulo sta->eapol_sm->dot1xAuthEapolFramesTx++; 206e28a4053SRui Paulo os_free(buf); 207e28a4053SRui Paulo } 208e28a4053SRui Paulo 209e28a4053SRui Paulo 210*325151a3SRui Paulo static void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta) 211e28a4053SRui Paulo { 212e28a4053SRui Paulo struct eapol_authenticator *eapol = hapd->eapol_auth; 213e28a4053SRui Paulo struct eapol_state_machine *sm = sta->eapol_sm; 214e28a4053SRui Paulo 215e28a4053SRui Paulo if (sm == NULL || !sm->eap_if->eapKeyData) 216e28a4053SRui Paulo return; 217e28a4053SRui Paulo 218e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "IEEE 802.1X: Sending EAPOL-Key(s) to " MACSTR, 219e28a4053SRui Paulo MAC2STR(sta->addr)); 220e28a4053SRui Paulo 221e28a4053SRui Paulo #ifndef CONFIG_NO_VLAN 2225b9c547cSRui Paulo if (sta->vlan_id > 0 && sta->vlan_id <= MAX_VLAN_ID) { 2235b9c547cSRui Paulo wpa_printf(MSG_ERROR, "Using WEP with vlans is not supported."); 2245b9c547cSRui Paulo return; 2255b9c547cSRui Paulo } 226e28a4053SRui Paulo #endif /* CONFIG_NO_VLAN */ 2275b9c547cSRui Paulo 228e28a4053SRui Paulo if (eapol->default_wep_key) { 229e28a4053SRui Paulo ieee802_1x_tx_key_one(hapd, sta, eapol->default_wep_key_idx, 1, 230e28a4053SRui Paulo eapol->default_wep_key, 231e28a4053SRui Paulo hapd->conf->default_wep_key_len); 232e28a4053SRui Paulo } 233e28a4053SRui Paulo 234e28a4053SRui Paulo if (hapd->conf->individual_wep_key_len > 0) { 235e28a4053SRui Paulo u8 *ikey; 236e28a4053SRui Paulo ikey = os_malloc(hapd->conf->individual_wep_key_len); 237e28a4053SRui Paulo if (ikey == NULL || 238f05cddf9SRui Paulo random_get_bytes(ikey, hapd->conf->individual_wep_key_len)) 239f05cddf9SRui Paulo { 240e28a4053SRui Paulo wpa_printf(MSG_ERROR, "Could not generate random " 241e28a4053SRui Paulo "individual WEP key."); 242e28a4053SRui Paulo os_free(ikey); 243e28a4053SRui Paulo return; 244e28a4053SRui Paulo } 245e28a4053SRui Paulo 246e28a4053SRui Paulo wpa_hexdump_key(MSG_DEBUG, "Individual WEP key", 247e28a4053SRui Paulo ikey, hapd->conf->individual_wep_key_len); 248e28a4053SRui Paulo 249e28a4053SRui Paulo ieee802_1x_tx_key_one(hapd, sta, 0, 0, ikey, 250e28a4053SRui Paulo hapd->conf->individual_wep_key_len); 251e28a4053SRui Paulo 252e28a4053SRui Paulo /* TODO: set encryption in TX callback, i.e., only after STA 253e28a4053SRui Paulo * has ACKed EAPOL-Key frame */ 254f05cddf9SRui Paulo if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, 255e28a4053SRui Paulo sta->addr, 0, 1, NULL, 0, ikey, 256e28a4053SRui Paulo hapd->conf->individual_wep_key_len)) { 257e28a4053SRui Paulo wpa_printf(MSG_ERROR, "Could not set individual WEP " 258e28a4053SRui Paulo "encryption."); 259e28a4053SRui Paulo } 260e28a4053SRui Paulo 261e28a4053SRui Paulo os_free(ikey); 262e28a4053SRui Paulo } 263e28a4053SRui Paulo } 264e28a4053SRui Paulo 265*325151a3SRui Paulo #endif /* CONFIG_NO_RC4 */ 266*325151a3SRui Paulo #endif /* CONFIG_FIPS */ 267*325151a3SRui Paulo 268e28a4053SRui Paulo 269e28a4053SRui Paulo const char *radius_mode_txt(struct hostapd_data *hapd) 270e28a4053SRui Paulo { 271e28a4053SRui Paulo switch (hapd->iface->conf->hw_mode) { 272f05cddf9SRui Paulo case HOSTAPD_MODE_IEEE80211AD: 273f05cddf9SRui Paulo return "802.11ad"; 274e28a4053SRui Paulo case HOSTAPD_MODE_IEEE80211A: 275e28a4053SRui Paulo return "802.11a"; 276e28a4053SRui Paulo case HOSTAPD_MODE_IEEE80211G: 277e28a4053SRui Paulo return "802.11g"; 278e28a4053SRui Paulo case HOSTAPD_MODE_IEEE80211B: 279e28a4053SRui Paulo default: 280e28a4053SRui Paulo return "802.11b"; 281e28a4053SRui Paulo } 282e28a4053SRui Paulo } 283e28a4053SRui Paulo 284e28a4053SRui Paulo 285e28a4053SRui Paulo int radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta) 286e28a4053SRui Paulo { 287e28a4053SRui Paulo int i; 288e28a4053SRui Paulo u8 rate = 0; 289e28a4053SRui Paulo 290e28a4053SRui Paulo for (i = 0; i < sta->supported_rates_len; i++) 291e28a4053SRui Paulo if ((sta->supported_rates[i] & 0x7f) > rate) 292e28a4053SRui Paulo rate = sta->supported_rates[i] & 0x7f; 293e28a4053SRui Paulo 294e28a4053SRui Paulo return rate; 295e28a4053SRui Paulo } 296e28a4053SRui Paulo 297e28a4053SRui Paulo 298e28a4053SRui Paulo #ifndef CONFIG_NO_RADIUS 299e28a4053SRui Paulo static void ieee802_1x_learn_identity(struct hostapd_data *hapd, 300e28a4053SRui Paulo struct eapol_state_machine *sm, 301e28a4053SRui Paulo const u8 *eap, size_t len) 302e28a4053SRui Paulo { 303e28a4053SRui Paulo const u8 *identity; 304e28a4053SRui Paulo size_t identity_len; 3055b9c547cSRui Paulo const struct eap_hdr *hdr = (const struct eap_hdr *) eap; 306e28a4053SRui Paulo 307e28a4053SRui Paulo if (len <= sizeof(struct eap_hdr) || 3085b9c547cSRui Paulo (hdr->code == EAP_CODE_RESPONSE && 3095b9c547cSRui Paulo eap[sizeof(struct eap_hdr)] != EAP_TYPE_IDENTITY) || 3105b9c547cSRui Paulo (hdr->code == EAP_CODE_INITIATE && 3115b9c547cSRui Paulo eap[sizeof(struct eap_hdr)] != EAP_ERP_TYPE_REAUTH) || 3125b9c547cSRui Paulo (hdr->code != EAP_CODE_RESPONSE && 3135b9c547cSRui Paulo hdr->code != EAP_CODE_INITIATE)) 314e28a4053SRui Paulo return; 315e28a4053SRui Paulo 316e28a4053SRui Paulo identity = eap_get_identity(sm->eap, &identity_len); 317e28a4053SRui Paulo if (identity == NULL) 318e28a4053SRui Paulo return; 319e28a4053SRui Paulo 320e28a4053SRui Paulo /* Save station identity for future RADIUS packets */ 321e28a4053SRui Paulo os_free(sm->identity); 3225b9c547cSRui Paulo sm->identity = (u8 *) dup_binstr(identity, identity_len); 323e28a4053SRui Paulo if (sm->identity == NULL) { 324e28a4053SRui Paulo sm->identity_len = 0; 325e28a4053SRui Paulo return; 326e28a4053SRui Paulo } 327e28a4053SRui Paulo 328e28a4053SRui Paulo sm->identity_len = identity_len; 329e28a4053SRui Paulo hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X, 330e28a4053SRui Paulo HOSTAPD_LEVEL_DEBUG, "STA identity '%s'", sm->identity); 331e28a4053SRui Paulo sm->dot1xAuthEapolRespIdFramesRx++; 332e28a4053SRui Paulo } 333e28a4053SRui Paulo 334e28a4053SRui Paulo 3355b9c547cSRui Paulo static int add_common_radius_sta_attr_rsn(struct hostapd_data *hapd, 3365b9c547cSRui Paulo struct hostapd_radius_attr *req_attr, 3375b9c547cSRui Paulo struct sta_info *sta, 3385b9c547cSRui Paulo struct radius_msg *msg) 3395b9c547cSRui Paulo { 3405b9c547cSRui Paulo u32 suite; 3415b9c547cSRui Paulo int ver, val; 3425b9c547cSRui Paulo 3435b9c547cSRui Paulo ver = wpa_auth_sta_wpa_version(sta->wpa_sm); 3445b9c547cSRui Paulo val = wpa_auth_get_pairwise(sta->wpa_sm); 3455b9c547cSRui Paulo suite = wpa_cipher_to_suite(ver, val); 3465b9c547cSRui Paulo if (val != -1 && 3475b9c547cSRui Paulo !hostapd_config_get_radius_attr(req_attr, 3485b9c547cSRui Paulo RADIUS_ATTR_WLAN_PAIRWISE_CIPHER) && 3495b9c547cSRui Paulo !radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_PAIRWISE_CIPHER, 3505b9c547cSRui Paulo suite)) { 3515b9c547cSRui Paulo wpa_printf(MSG_ERROR, "Could not add WLAN-Pairwise-Cipher"); 3525b9c547cSRui Paulo return -1; 3535b9c547cSRui Paulo } 3545b9c547cSRui Paulo 355*325151a3SRui Paulo suite = wpa_cipher_to_suite(((hapd->conf->wpa & 0x2) || 356*325151a3SRui Paulo hapd->conf->osen) ? 3575b9c547cSRui Paulo WPA_PROTO_RSN : WPA_PROTO_WPA, 3585b9c547cSRui Paulo hapd->conf->wpa_group); 3595b9c547cSRui Paulo if (!hostapd_config_get_radius_attr(req_attr, 3605b9c547cSRui Paulo RADIUS_ATTR_WLAN_GROUP_CIPHER) && 3615b9c547cSRui Paulo !radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_GROUP_CIPHER, 3625b9c547cSRui Paulo suite)) { 3635b9c547cSRui Paulo wpa_printf(MSG_ERROR, "Could not add WLAN-Group-Cipher"); 3645b9c547cSRui Paulo return -1; 3655b9c547cSRui Paulo } 3665b9c547cSRui Paulo 3675b9c547cSRui Paulo val = wpa_auth_sta_key_mgmt(sta->wpa_sm); 3685b9c547cSRui Paulo suite = wpa_akm_to_suite(val); 3695b9c547cSRui Paulo if (val != -1 && 3705b9c547cSRui Paulo !hostapd_config_get_radius_attr(req_attr, 3715b9c547cSRui Paulo RADIUS_ATTR_WLAN_AKM_SUITE) && 3725b9c547cSRui Paulo !radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_AKM_SUITE, 3735b9c547cSRui Paulo suite)) { 3745b9c547cSRui Paulo wpa_printf(MSG_ERROR, "Could not add WLAN-AKM-Suite"); 3755b9c547cSRui Paulo return -1; 3765b9c547cSRui Paulo } 3775b9c547cSRui Paulo 3785b9c547cSRui Paulo #ifdef CONFIG_IEEE80211W 3795b9c547cSRui Paulo if (hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 3805b9c547cSRui Paulo suite = wpa_cipher_to_suite(WPA_PROTO_RSN, 3815b9c547cSRui Paulo hapd->conf->group_mgmt_cipher); 3825b9c547cSRui Paulo if (!hostapd_config_get_radius_attr( 3835b9c547cSRui Paulo req_attr, RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER) && 3845b9c547cSRui Paulo !radius_msg_add_attr_int32( 3855b9c547cSRui Paulo msg, RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER, suite)) { 3865b9c547cSRui Paulo wpa_printf(MSG_ERROR, 3875b9c547cSRui Paulo "Could not add WLAN-Group-Mgmt-Cipher"); 3885b9c547cSRui Paulo return -1; 3895b9c547cSRui Paulo } 3905b9c547cSRui Paulo } 3915b9c547cSRui Paulo #endif /* CONFIG_IEEE80211W */ 3925b9c547cSRui Paulo 3935b9c547cSRui Paulo return 0; 3945b9c547cSRui Paulo } 3955b9c547cSRui Paulo 3965b9c547cSRui Paulo 397f05cddf9SRui Paulo static int add_common_radius_sta_attr(struct hostapd_data *hapd, 398f05cddf9SRui Paulo struct hostapd_radius_attr *req_attr, 399f05cddf9SRui Paulo struct sta_info *sta, 400f05cddf9SRui Paulo struct radius_msg *msg) 401f05cddf9SRui Paulo { 402f05cddf9SRui Paulo char buf[128]; 403f05cddf9SRui Paulo 404f05cddf9SRui Paulo if (!hostapd_config_get_radius_attr(req_attr, 405f05cddf9SRui Paulo RADIUS_ATTR_NAS_PORT) && 406f05cddf9SRui Paulo !radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) { 407f05cddf9SRui Paulo wpa_printf(MSG_ERROR, "Could not add NAS-Port"); 408f05cddf9SRui Paulo return -1; 409f05cddf9SRui Paulo } 410f05cddf9SRui Paulo 411f05cddf9SRui Paulo os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, 412f05cddf9SRui Paulo MAC2STR(sta->addr)); 413f05cddf9SRui Paulo buf[sizeof(buf) - 1] = '\0'; 414f05cddf9SRui Paulo if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, 415f05cddf9SRui Paulo (u8 *) buf, os_strlen(buf))) { 416f05cddf9SRui Paulo wpa_printf(MSG_ERROR, "Could not add Calling-Station-Id"); 417f05cddf9SRui Paulo return -1; 418f05cddf9SRui Paulo } 419f05cddf9SRui Paulo 420f05cddf9SRui Paulo if (sta->flags & WLAN_STA_PREAUTH) { 421f05cddf9SRui Paulo os_strlcpy(buf, "IEEE 802.11i Pre-Authentication", 422f05cddf9SRui Paulo sizeof(buf)); 423f05cddf9SRui Paulo } else { 424f05cddf9SRui Paulo os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s", 425f05cddf9SRui Paulo radius_sta_rate(hapd, sta) / 2, 426f05cddf9SRui Paulo (radius_sta_rate(hapd, sta) & 1) ? ".5" : "", 427f05cddf9SRui Paulo radius_mode_txt(hapd)); 428f05cddf9SRui Paulo buf[sizeof(buf) - 1] = '\0'; 429f05cddf9SRui Paulo } 430f05cddf9SRui Paulo if (!hostapd_config_get_radius_attr(req_attr, 431f05cddf9SRui Paulo RADIUS_ATTR_CONNECT_INFO) && 432f05cddf9SRui Paulo !radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, 433f05cddf9SRui Paulo (u8 *) buf, os_strlen(buf))) { 434f05cddf9SRui Paulo wpa_printf(MSG_ERROR, "Could not add Connect-Info"); 435f05cddf9SRui Paulo return -1; 436f05cddf9SRui Paulo } 437f05cddf9SRui Paulo 438f05cddf9SRui Paulo if (sta->acct_session_id_hi || sta->acct_session_id_lo) { 439f05cddf9SRui Paulo os_snprintf(buf, sizeof(buf), "%08X-%08X", 440f05cddf9SRui Paulo sta->acct_session_id_hi, sta->acct_session_id_lo); 441f05cddf9SRui Paulo if (!radius_msg_add_attr(msg, RADIUS_ATTR_ACCT_SESSION_ID, 442f05cddf9SRui Paulo (u8 *) buf, os_strlen(buf))) { 443f05cddf9SRui Paulo wpa_printf(MSG_ERROR, "Could not add Acct-Session-Id"); 444f05cddf9SRui Paulo return -1; 445f05cddf9SRui Paulo } 446f05cddf9SRui Paulo } 447f05cddf9SRui Paulo 4485b9c547cSRui Paulo #ifdef CONFIG_IEEE80211R 4495b9c547cSRui Paulo if (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) && 4505b9c547cSRui Paulo sta->wpa_sm && 4515b9c547cSRui Paulo (wpa_key_mgmt_ft(wpa_auth_sta_key_mgmt(sta->wpa_sm)) || 4525b9c547cSRui Paulo sta->auth_alg == WLAN_AUTH_FT) && 4535b9c547cSRui Paulo !hostapd_config_get_radius_attr(req_attr, 4545b9c547cSRui Paulo RADIUS_ATTR_MOBILITY_DOMAIN_ID) && 4555b9c547cSRui Paulo !radius_msg_add_attr_int32(msg, RADIUS_ATTR_MOBILITY_DOMAIN_ID, 4565b9c547cSRui Paulo WPA_GET_BE16( 4575b9c547cSRui Paulo hapd->conf->mobility_domain))) { 4585b9c547cSRui Paulo wpa_printf(MSG_ERROR, "Could not add Mobility-Domain-Id"); 4595b9c547cSRui Paulo return -1; 4605b9c547cSRui Paulo } 4615b9c547cSRui Paulo #endif /* CONFIG_IEEE80211R */ 4625b9c547cSRui Paulo 463*325151a3SRui Paulo if ((hapd->conf->wpa || hapd->conf->osen) && sta->wpa_sm && 4645b9c547cSRui Paulo add_common_radius_sta_attr_rsn(hapd, req_attr, sta, msg) < 0) 4655b9c547cSRui Paulo return -1; 4665b9c547cSRui Paulo 467f05cddf9SRui Paulo return 0; 468f05cddf9SRui Paulo } 469f05cddf9SRui Paulo 470f05cddf9SRui Paulo 471f05cddf9SRui Paulo int add_common_radius_attr(struct hostapd_data *hapd, 472f05cddf9SRui Paulo struct hostapd_radius_attr *req_attr, 473f05cddf9SRui Paulo struct sta_info *sta, 474f05cddf9SRui Paulo struct radius_msg *msg) 475f05cddf9SRui Paulo { 476f05cddf9SRui Paulo char buf[128]; 477f05cddf9SRui Paulo struct hostapd_radius_attr *attr; 478f05cddf9SRui Paulo 479f05cddf9SRui Paulo if (!hostapd_config_get_radius_attr(req_attr, 480f05cddf9SRui Paulo RADIUS_ATTR_NAS_IP_ADDRESS) && 481f05cddf9SRui Paulo hapd->conf->own_ip_addr.af == AF_INET && 482f05cddf9SRui Paulo !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, 483f05cddf9SRui Paulo (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) { 484f05cddf9SRui Paulo wpa_printf(MSG_ERROR, "Could not add NAS-IP-Address"); 485f05cddf9SRui Paulo return -1; 486f05cddf9SRui Paulo } 487f05cddf9SRui Paulo 488f05cddf9SRui Paulo #ifdef CONFIG_IPV6 489f05cddf9SRui Paulo if (!hostapd_config_get_radius_attr(req_attr, 490f05cddf9SRui Paulo RADIUS_ATTR_NAS_IPV6_ADDRESS) && 491f05cddf9SRui Paulo hapd->conf->own_ip_addr.af == AF_INET6 && 492f05cddf9SRui Paulo !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, 493f05cddf9SRui Paulo (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) { 494f05cddf9SRui Paulo wpa_printf(MSG_ERROR, "Could not add NAS-IPv6-Address"); 495f05cddf9SRui Paulo return -1; 496f05cddf9SRui Paulo } 497f05cddf9SRui Paulo #endif /* CONFIG_IPV6 */ 498f05cddf9SRui Paulo 499f05cddf9SRui Paulo if (!hostapd_config_get_radius_attr(req_attr, 500f05cddf9SRui Paulo RADIUS_ATTR_NAS_IDENTIFIER) && 501f05cddf9SRui Paulo hapd->conf->nas_identifier && 502f05cddf9SRui Paulo !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, 503f05cddf9SRui Paulo (u8 *) hapd->conf->nas_identifier, 504f05cddf9SRui Paulo os_strlen(hapd->conf->nas_identifier))) { 505f05cddf9SRui Paulo wpa_printf(MSG_ERROR, "Could not add NAS-Identifier"); 506f05cddf9SRui Paulo return -1; 507f05cddf9SRui Paulo } 508f05cddf9SRui Paulo 509f05cddf9SRui Paulo os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", 510f05cddf9SRui Paulo MAC2STR(hapd->own_addr), 511f05cddf9SRui Paulo wpa_ssid_txt(hapd->conf->ssid.ssid, 512f05cddf9SRui Paulo hapd->conf->ssid.ssid_len)); 513f05cddf9SRui Paulo buf[sizeof(buf) - 1] = '\0'; 514f05cddf9SRui Paulo if (!hostapd_config_get_radius_attr(req_attr, 515f05cddf9SRui Paulo RADIUS_ATTR_CALLED_STATION_ID) && 516f05cddf9SRui Paulo !radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, 517f05cddf9SRui Paulo (u8 *) buf, os_strlen(buf))) { 518f05cddf9SRui Paulo wpa_printf(MSG_ERROR, "Could not add Called-Station-Id"); 519f05cddf9SRui Paulo return -1; 520f05cddf9SRui Paulo } 521f05cddf9SRui Paulo 522f05cddf9SRui Paulo if (!hostapd_config_get_radius_attr(req_attr, 523f05cddf9SRui Paulo RADIUS_ATTR_NAS_PORT_TYPE) && 524f05cddf9SRui Paulo !radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, 525f05cddf9SRui Paulo RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { 526f05cddf9SRui Paulo wpa_printf(MSG_ERROR, "Could not add NAS-Port-Type"); 527f05cddf9SRui Paulo return -1; 528f05cddf9SRui Paulo } 529f05cddf9SRui Paulo 5305b9c547cSRui Paulo #ifdef CONFIG_INTERWORKING 5315b9c547cSRui Paulo if (hapd->conf->interworking && 5325b9c547cSRui Paulo !is_zero_ether_addr(hapd->conf->hessid)) { 5335b9c547cSRui Paulo os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, 5345b9c547cSRui Paulo MAC2STR(hapd->conf->hessid)); 5355b9c547cSRui Paulo buf[sizeof(buf) - 1] = '\0'; 5365b9c547cSRui Paulo if (!hostapd_config_get_radius_attr(req_attr, 5375b9c547cSRui Paulo RADIUS_ATTR_WLAN_HESSID) && 5385b9c547cSRui Paulo !radius_msg_add_attr(msg, RADIUS_ATTR_WLAN_HESSID, 5395b9c547cSRui Paulo (u8 *) buf, os_strlen(buf))) { 5405b9c547cSRui Paulo wpa_printf(MSG_ERROR, "Could not add WLAN-HESSID"); 5415b9c547cSRui Paulo return -1; 5425b9c547cSRui Paulo } 5435b9c547cSRui Paulo } 5445b9c547cSRui Paulo #endif /* CONFIG_INTERWORKING */ 5455b9c547cSRui Paulo 546f05cddf9SRui Paulo if (sta && add_common_radius_sta_attr(hapd, req_attr, sta, msg) < 0) 547f05cddf9SRui Paulo return -1; 548f05cddf9SRui Paulo 549f05cddf9SRui Paulo for (attr = req_attr; attr; attr = attr->next) { 550f05cddf9SRui Paulo if (!radius_msg_add_attr(msg, attr->type, 551f05cddf9SRui Paulo wpabuf_head(attr->val), 552f05cddf9SRui Paulo wpabuf_len(attr->val))) { 553f05cddf9SRui Paulo wpa_printf(MSG_ERROR, "Could not add RADIUS " 554f05cddf9SRui Paulo "attribute"); 555f05cddf9SRui Paulo return -1; 556f05cddf9SRui Paulo } 557f05cddf9SRui Paulo } 558f05cddf9SRui Paulo 559f05cddf9SRui Paulo return 0; 560f05cddf9SRui Paulo } 561f05cddf9SRui Paulo 562f05cddf9SRui Paulo 563e28a4053SRui Paulo static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd, 564e28a4053SRui Paulo struct sta_info *sta, 565e28a4053SRui Paulo const u8 *eap, size_t len) 566e28a4053SRui Paulo { 567e28a4053SRui Paulo struct radius_msg *msg; 568e28a4053SRui Paulo struct eapol_state_machine *sm = sta->eapol_sm; 569e28a4053SRui Paulo 570e28a4053SRui Paulo if (sm == NULL) 571e28a4053SRui Paulo return; 572e28a4053SRui Paulo 573e28a4053SRui Paulo ieee802_1x_learn_identity(hapd, sm, eap, len); 574e28a4053SRui Paulo 575e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS " 576e28a4053SRui Paulo "packet"); 577e28a4053SRui Paulo 578e28a4053SRui Paulo sm->radius_identifier = radius_client_get_id(hapd->radius); 579e28a4053SRui Paulo msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, 580e28a4053SRui Paulo sm->radius_identifier); 581e28a4053SRui Paulo if (msg == NULL) { 5825b9c547cSRui Paulo wpa_printf(MSG_INFO, "Could not create new RADIUS packet"); 583e28a4053SRui Paulo return; 584e28a4053SRui Paulo } 585e28a4053SRui Paulo 586e28a4053SRui Paulo radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta)); 587e28a4053SRui Paulo 588e28a4053SRui Paulo if (sm->identity && 589e28a4053SRui Paulo !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, 590e28a4053SRui Paulo sm->identity, sm->identity_len)) { 5915b9c547cSRui Paulo wpa_printf(MSG_INFO, "Could not add User-Name"); 592e28a4053SRui Paulo goto fail; 593e28a4053SRui Paulo } 594e28a4053SRui Paulo 595f05cddf9SRui Paulo if (add_common_radius_attr(hapd, hapd->conf->radius_auth_req_attr, sta, 596f05cddf9SRui Paulo msg) < 0) 597e28a4053SRui Paulo goto fail; 598e28a4053SRui Paulo 599e28a4053SRui Paulo /* TODO: should probably check MTU from driver config; 2304 is max for 600e28a4053SRui Paulo * IEEE 802.11, but use 1400 to avoid problems with too large packets 601e28a4053SRui Paulo */ 602f05cddf9SRui Paulo if (!hostapd_config_get_radius_attr(hapd->conf->radius_auth_req_attr, 603f05cddf9SRui Paulo RADIUS_ATTR_FRAMED_MTU) && 604f05cddf9SRui Paulo !radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) { 6055b9c547cSRui Paulo wpa_printf(MSG_INFO, "Could not add Framed-MTU"); 606e28a4053SRui Paulo goto fail; 607e28a4053SRui Paulo } 608e28a4053SRui Paulo 609*325151a3SRui Paulo if (!radius_msg_add_eap(msg, eap, len)) { 6105b9c547cSRui Paulo wpa_printf(MSG_INFO, "Could not add EAP-Message"); 611e28a4053SRui Paulo goto fail; 612e28a4053SRui Paulo } 613e28a4053SRui Paulo 614e28a4053SRui Paulo /* State attribute must be copied if and only if this packet is 615e28a4053SRui Paulo * Access-Request reply to the previous Access-Challenge */ 616e28a4053SRui Paulo if (sm->last_recv_radius && 617e28a4053SRui Paulo radius_msg_get_hdr(sm->last_recv_radius)->code == 618e28a4053SRui Paulo RADIUS_CODE_ACCESS_CHALLENGE) { 619e28a4053SRui Paulo int res = radius_msg_copy_attr(msg, sm->last_recv_radius, 620e28a4053SRui Paulo RADIUS_ATTR_STATE); 621e28a4053SRui Paulo if (res < 0) { 6225b9c547cSRui Paulo wpa_printf(MSG_INFO, "Could not copy State attribute from previous Access-Challenge"); 623e28a4053SRui Paulo goto fail; 624e28a4053SRui Paulo } 625e28a4053SRui Paulo if (res > 0) { 626e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "Copied RADIUS State Attribute"); 627e28a4053SRui Paulo } 628e28a4053SRui Paulo } 629e28a4053SRui Paulo 630f05cddf9SRui Paulo if (hapd->conf->radius_request_cui) { 631f05cddf9SRui Paulo const u8 *cui; 632f05cddf9SRui Paulo size_t cui_len; 633f05cddf9SRui Paulo /* Add previously learned CUI or nul CUI to request CUI */ 634f05cddf9SRui Paulo if (sm->radius_cui) { 635f05cddf9SRui Paulo cui = wpabuf_head(sm->radius_cui); 636f05cddf9SRui Paulo cui_len = wpabuf_len(sm->radius_cui); 637f05cddf9SRui Paulo } else { 638f05cddf9SRui Paulo cui = (const u8 *) "\0"; 639f05cddf9SRui Paulo cui_len = 1; 640f05cddf9SRui Paulo } 641f05cddf9SRui Paulo if (!radius_msg_add_attr(msg, 642f05cddf9SRui Paulo RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, 643f05cddf9SRui Paulo cui, cui_len)) { 644f05cddf9SRui Paulo wpa_printf(MSG_ERROR, "Could not add CUI"); 645f05cddf9SRui Paulo goto fail; 646f05cddf9SRui Paulo } 647f05cddf9SRui Paulo } 648f05cddf9SRui Paulo 6495b9c547cSRui Paulo #ifdef CONFIG_HS20 6505b9c547cSRui Paulo if (hapd->conf->hs20) { 6515b9c547cSRui Paulo u8 ver = 1; /* Release 2 */ 6525b9c547cSRui Paulo if (!radius_msg_add_wfa( 6535b9c547cSRui Paulo msg, RADIUS_VENDOR_ATTR_WFA_HS20_AP_VERSION, 6545b9c547cSRui Paulo &ver, 1)) { 6555b9c547cSRui Paulo wpa_printf(MSG_ERROR, "Could not add HS 2.0 AP " 6565b9c547cSRui Paulo "version"); 6575b9c547cSRui Paulo goto fail; 6585b9c547cSRui Paulo } 6595b9c547cSRui Paulo 6605b9c547cSRui Paulo if (sta->hs20_ie && wpabuf_len(sta->hs20_ie) > 0) { 6615b9c547cSRui Paulo const u8 *pos; 6625b9c547cSRui Paulo u8 buf[3]; 6635b9c547cSRui Paulo u16 id; 6645b9c547cSRui Paulo pos = wpabuf_head_u8(sta->hs20_ie); 6655b9c547cSRui Paulo buf[0] = (*pos) >> 4; 6665b9c547cSRui Paulo if (((*pos) & HS20_PPS_MO_ID_PRESENT) && 6675b9c547cSRui Paulo wpabuf_len(sta->hs20_ie) >= 3) 6685b9c547cSRui Paulo id = WPA_GET_LE16(pos + 1); 6695b9c547cSRui Paulo else 6705b9c547cSRui Paulo id = 0; 6715b9c547cSRui Paulo WPA_PUT_BE16(buf + 1, id); 6725b9c547cSRui Paulo if (!radius_msg_add_wfa( 6735b9c547cSRui Paulo msg, 6745b9c547cSRui Paulo RADIUS_VENDOR_ATTR_WFA_HS20_STA_VERSION, 6755b9c547cSRui Paulo buf, sizeof(buf))) { 6765b9c547cSRui Paulo wpa_printf(MSG_ERROR, "Could not add HS 2.0 " 6775b9c547cSRui Paulo "STA version"); 6785b9c547cSRui Paulo goto fail; 6795b9c547cSRui Paulo } 6805b9c547cSRui Paulo } 6815b9c547cSRui Paulo } 6825b9c547cSRui Paulo #endif /* CONFIG_HS20 */ 6835b9c547cSRui Paulo 684f05cddf9SRui Paulo if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, sta->addr) < 0) 685f05cddf9SRui Paulo goto fail; 686f05cddf9SRui Paulo 687e28a4053SRui Paulo return; 688e28a4053SRui Paulo 689e28a4053SRui Paulo fail: 690e28a4053SRui Paulo radius_msg_free(msg); 691e28a4053SRui Paulo } 692e28a4053SRui Paulo #endif /* CONFIG_NO_RADIUS */ 693e28a4053SRui Paulo 694e28a4053SRui Paulo 695e28a4053SRui Paulo static void handle_eap_response(struct hostapd_data *hapd, 696e28a4053SRui Paulo struct sta_info *sta, struct eap_hdr *eap, 697e28a4053SRui Paulo size_t len) 698e28a4053SRui Paulo { 699e28a4053SRui Paulo u8 type, *data; 700e28a4053SRui Paulo struct eapol_state_machine *sm = sta->eapol_sm; 701e28a4053SRui Paulo if (sm == NULL) 702e28a4053SRui Paulo return; 703e28a4053SRui Paulo 704e28a4053SRui Paulo data = (u8 *) (eap + 1); 705e28a4053SRui Paulo 706e28a4053SRui Paulo if (len < sizeof(*eap) + 1) { 7075b9c547cSRui Paulo wpa_printf(MSG_INFO, "handle_eap_response: too short response data"); 708e28a4053SRui Paulo return; 709e28a4053SRui Paulo } 710e28a4053SRui Paulo 711e28a4053SRui Paulo sm->eap_type_supp = type = data[0]; 712e28a4053SRui Paulo 713e28a4053SRui Paulo hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X, 714e28a4053SRui Paulo HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d " 715e28a4053SRui Paulo "id=%d len=%d) from STA: EAP Response-%s (%d)", 716e28a4053SRui Paulo eap->code, eap->identifier, be_to_host16(eap->length), 717e28a4053SRui Paulo eap_server_get_name(0, type), type); 718e28a4053SRui Paulo 719e28a4053SRui Paulo sm->dot1xAuthEapolRespFramesRx++; 720e28a4053SRui Paulo 721e28a4053SRui Paulo wpabuf_free(sm->eap_if->eapRespData); 722e28a4053SRui Paulo sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len); 723e28a4053SRui Paulo sm->eapolEap = TRUE; 724e28a4053SRui Paulo } 725e28a4053SRui Paulo 726e28a4053SRui Paulo 7275b9c547cSRui Paulo static void handle_eap_initiate(struct hostapd_data *hapd, 7285b9c547cSRui Paulo struct sta_info *sta, struct eap_hdr *eap, 7295b9c547cSRui Paulo size_t len) 7305b9c547cSRui Paulo { 7315b9c547cSRui Paulo #ifdef CONFIG_ERP 7325b9c547cSRui Paulo u8 type, *data; 7335b9c547cSRui Paulo struct eapol_state_machine *sm = sta->eapol_sm; 7345b9c547cSRui Paulo 7355b9c547cSRui Paulo if (sm == NULL) 7365b9c547cSRui Paulo return; 7375b9c547cSRui Paulo 7385b9c547cSRui Paulo if (len < sizeof(*eap) + 1) { 7395b9c547cSRui Paulo wpa_printf(MSG_INFO, 7405b9c547cSRui Paulo "handle_eap_initiate: too short response data"); 7415b9c547cSRui Paulo return; 7425b9c547cSRui Paulo } 7435b9c547cSRui Paulo 7445b9c547cSRui Paulo data = (u8 *) (eap + 1); 7455b9c547cSRui Paulo type = data[0]; 7465b9c547cSRui Paulo 7475b9c547cSRui Paulo hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X, 7485b9c547cSRui Paulo HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d " 7495b9c547cSRui Paulo "id=%d len=%d) from STA: EAP Initiate type %u", 7505b9c547cSRui Paulo eap->code, eap->identifier, be_to_host16(eap->length), 7515b9c547cSRui Paulo type); 7525b9c547cSRui Paulo 7535b9c547cSRui Paulo wpabuf_free(sm->eap_if->eapRespData); 7545b9c547cSRui Paulo sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len); 7555b9c547cSRui Paulo sm->eapolEap = TRUE; 7565b9c547cSRui Paulo #endif /* CONFIG_ERP */ 7575b9c547cSRui Paulo } 7585b9c547cSRui Paulo 7595b9c547cSRui Paulo 760e28a4053SRui Paulo /* Process incoming EAP packet from Supplicant */ 761e28a4053SRui Paulo static void handle_eap(struct hostapd_data *hapd, struct sta_info *sta, 762e28a4053SRui Paulo u8 *buf, size_t len) 763e28a4053SRui Paulo { 764e28a4053SRui Paulo struct eap_hdr *eap; 765e28a4053SRui Paulo u16 eap_len; 766e28a4053SRui Paulo 767e28a4053SRui Paulo if (len < sizeof(*eap)) { 7685b9c547cSRui Paulo wpa_printf(MSG_INFO, " too short EAP packet"); 769e28a4053SRui Paulo return; 770e28a4053SRui Paulo } 771e28a4053SRui Paulo 772e28a4053SRui Paulo eap = (struct eap_hdr *) buf; 773e28a4053SRui Paulo 774e28a4053SRui Paulo eap_len = be_to_host16(eap->length); 775e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "EAP: code=%d identifier=%d length=%d", 776e28a4053SRui Paulo eap->code, eap->identifier, eap_len); 777e28a4053SRui Paulo if (eap_len < sizeof(*eap)) { 778e28a4053SRui Paulo wpa_printf(MSG_DEBUG, " Invalid EAP length"); 779e28a4053SRui Paulo return; 780e28a4053SRui Paulo } else if (eap_len > len) { 781e28a4053SRui Paulo wpa_printf(MSG_DEBUG, " Too short frame to contain this EAP " 782e28a4053SRui Paulo "packet"); 783e28a4053SRui Paulo return; 784e28a4053SRui Paulo } else if (eap_len < len) { 785e28a4053SRui Paulo wpa_printf(MSG_DEBUG, " Ignoring %lu extra bytes after EAP " 786e28a4053SRui Paulo "packet", (unsigned long) len - eap_len); 787e28a4053SRui Paulo } 788e28a4053SRui Paulo 789e28a4053SRui Paulo switch (eap->code) { 790e28a4053SRui Paulo case EAP_CODE_REQUEST: 791e28a4053SRui Paulo wpa_printf(MSG_DEBUG, " (request)"); 792e28a4053SRui Paulo return; 793e28a4053SRui Paulo case EAP_CODE_RESPONSE: 794e28a4053SRui Paulo wpa_printf(MSG_DEBUG, " (response)"); 795e28a4053SRui Paulo handle_eap_response(hapd, sta, eap, eap_len); 796e28a4053SRui Paulo break; 797e28a4053SRui Paulo case EAP_CODE_SUCCESS: 798e28a4053SRui Paulo wpa_printf(MSG_DEBUG, " (success)"); 799e28a4053SRui Paulo return; 800e28a4053SRui Paulo case EAP_CODE_FAILURE: 801e28a4053SRui Paulo wpa_printf(MSG_DEBUG, " (failure)"); 802e28a4053SRui Paulo return; 8035b9c547cSRui Paulo case EAP_CODE_INITIATE: 8045b9c547cSRui Paulo wpa_printf(MSG_DEBUG, " (initiate)"); 8055b9c547cSRui Paulo handle_eap_initiate(hapd, sta, eap, eap_len); 8065b9c547cSRui Paulo break; 8075b9c547cSRui Paulo case EAP_CODE_FINISH: 8085b9c547cSRui Paulo wpa_printf(MSG_DEBUG, " (finish)"); 8095b9c547cSRui Paulo break; 810e28a4053SRui Paulo default: 811e28a4053SRui Paulo wpa_printf(MSG_DEBUG, " (unknown code)"); 812e28a4053SRui Paulo return; 813e28a4053SRui Paulo } 814e28a4053SRui Paulo } 815e28a4053SRui Paulo 816e28a4053SRui Paulo 817e28a4053SRui Paulo static struct eapol_state_machine * 818e28a4053SRui Paulo ieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta) 819e28a4053SRui Paulo { 820e28a4053SRui Paulo int flags = 0; 821e28a4053SRui Paulo if (sta->flags & WLAN_STA_PREAUTH) 822e28a4053SRui Paulo flags |= EAPOL_SM_PREAUTH; 823e28a4053SRui Paulo if (sta->wpa_sm) { 824e28a4053SRui Paulo flags |= EAPOL_SM_USES_WPA; 825e28a4053SRui Paulo if (wpa_auth_sta_get_pmksa(sta->wpa_sm)) 826e28a4053SRui Paulo flags |= EAPOL_SM_FROM_PMKSA_CACHE; 827e28a4053SRui Paulo } 828e28a4053SRui Paulo return eapol_auth_alloc(hapd->eapol_auth, sta->addr, flags, 829f05cddf9SRui Paulo sta->wps_ie, sta->p2p_ie, sta, 830f05cddf9SRui Paulo sta->identity, sta->radius_cui); 831e28a4053SRui Paulo } 832e28a4053SRui Paulo 833e28a4053SRui Paulo 834e28a4053SRui Paulo /** 835e28a4053SRui Paulo * ieee802_1x_receive - Process the EAPOL frames from the Supplicant 836e28a4053SRui Paulo * @hapd: hostapd BSS data 837e28a4053SRui Paulo * @sa: Source address (sender of the EAPOL frame) 838e28a4053SRui Paulo * @buf: EAPOL frame 839e28a4053SRui Paulo * @len: Length of buf in octets 840e28a4053SRui Paulo * 841e28a4053SRui Paulo * This function is called for each incoming EAPOL frame from the interface 842e28a4053SRui Paulo */ 843e28a4053SRui Paulo void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, 844e28a4053SRui Paulo size_t len) 845e28a4053SRui Paulo { 846e28a4053SRui Paulo struct sta_info *sta; 847e28a4053SRui Paulo struct ieee802_1x_hdr *hdr; 848e28a4053SRui Paulo struct ieee802_1x_eapol_key *key; 849e28a4053SRui Paulo u16 datalen; 850e28a4053SRui Paulo struct rsn_pmksa_cache_entry *pmksa; 851f05cddf9SRui Paulo int key_mgmt; 852e28a4053SRui Paulo 8535b9c547cSRui Paulo if (!hapd->conf->ieee802_1x && !hapd->conf->wpa && !hapd->conf->osen && 854e28a4053SRui Paulo !hapd->conf->wps_state) 855e28a4053SRui Paulo return; 856e28a4053SRui Paulo 857e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR, 858e28a4053SRui Paulo (unsigned long) len, MAC2STR(sa)); 859e28a4053SRui Paulo sta = ap_get_sta(hapd, sa); 860f05cddf9SRui Paulo if (!sta || (!(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH)) && 861f05cddf9SRui Paulo !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED))) { 862e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not " 863f05cddf9SRui Paulo "associated/Pre-authenticating STA"); 864e28a4053SRui Paulo return; 865e28a4053SRui Paulo } 866e28a4053SRui Paulo 867e28a4053SRui Paulo if (len < sizeof(*hdr)) { 8685b9c547cSRui Paulo wpa_printf(MSG_INFO, " too short IEEE 802.1X packet"); 869e28a4053SRui Paulo return; 870e28a4053SRui Paulo } 871e28a4053SRui Paulo 872e28a4053SRui Paulo hdr = (struct ieee802_1x_hdr *) buf; 873e28a4053SRui Paulo datalen = be_to_host16(hdr->length); 874e28a4053SRui Paulo wpa_printf(MSG_DEBUG, " IEEE 802.1X: version=%d type=%d length=%d", 875e28a4053SRui Paulo hdr->version, hdr->type, datalen); 876e28a4053SRui Paulo 877e28a4053SRui Paulo if (len - sizeof(*hdr) < datalen) { 8785b9c547cSRui Paulo wpa_printf(MSG_INFO, " frame too short for this IEEE 802.1X packet"); 879e28a4053SRui Paulo if (sta->eapol_sm) 880e28a4053SRui Paulo sta->eapol_sm->dot1xAuthEapLengthErrorFramesRx++; 881e28a4053SRui Paulo return; 882e28a4053SRui Paulo } 883e28a4053SRui Paulo if (len - sizeof(*hdr) > datalen) { 884e28a4053SRui Paulo wpa_printf(MSG_DEBUG, " ignoring %lu extra octets after " 885e28a4053SRui Paulo "IEEE 802.1X packet", 886e28a4053SRui Paulo (unsigned long) len - sizeof(*hdr) - datalen); 887e28a4053SRui Paulo } 888e28a4053SRui Paulo 889e28a4053SRui Paulo if (sta->eapol_sm) { 890e28a4053SRui Paulo sta->eapol_sm->dot1xAuthLastEapolFrameVersion = hdr->version; 891e28a4053SRui Paulo sta->eapol_sm->dot1xAuthEapolFramesRx++; 892e28a4053SRui Paulo } 893e28a4053SRui Paulo 894e28a4053SRui Paulo key = (struct ieee802_1x_eapol_key *) (hdr + 1); 895e28a4053SRui Paulo if (datalen >= sizeof(struct ieee802_1x_eapol_key) && 896e28a4053SRui Paulo hdr->type == IEEE802_1X_TYPE_EAPOL_KEY && 897e28a4053SRui Paulo (key->type == EAPOL_KEY_TYPE_WPA || 898e28a4053SRui Paulo key->type == EAPOL_KEY_TYPE_RSN)) { 899e28a4053SRui Paulo wpa_receive(hapd->wpa_auth, sta->wpa_sm, (u8 *) hdr, 900e28a4053SRui Paulo sizeof(*hdr) + datalen); 901e28a4053SRui Paulo return; 902e28a4053SRui Paulo } 903e28a4053SRui Paulo 9045b9c547cSRui Paulo if (!hapd->conf->ieee802_1x && !hapd->conf->osen && 905f05cddf9SRui Paulo !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) { 906f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - " 907f05cddf9SRui Paulo "802.1X not enabled and WPS not used"); 908e28a4053SRui Paulo return; 909f05cddf9SRui Paulo } 910f05cddf9SRui Paulo 911f05cddf9SRui Paulo key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm); 912f05cddf9SRui Paulo if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) { 913f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - " 914f05cddf9SRui Paulo "STA is using PSK"); 915f05cddf9SRui Paulo return; 916f05cddf9SRui Paulo } 917e28a4053SRui Paulo 918e28a4053SRui Paulo if (!sta->eapol_sm) { 919e28a4053SRui Paulo sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta); 920e28a4053SRui Paulo if (!sta->eapol_sm) 921e28a4053SRui Paulo return; 922e28a4053SRui Paulo 923e28a4053SRui Paulo #ifdef CONFIG_WPS 9245b9c547cSRui Paulo if (!hapd->conf->ieee802_1x && hapd->conf->wps_state) { 925f05cddf9SRui Paulo u32 wflags = sta->flags & (WLAN_STA_WPS | 926f05cddf9SRui Paulo WLAN_STA_WPS2 | 927f05cddf9SRui Paulo WLAN_STA_MAYBE_WPS); 928f05cddf9SRui Paulo if (wflags == WLAN_STA_MAYBE_WPS || 929f05cddf9SRui Paulo wflags == (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) { 930e28a4053SRui Paulo /* 931f05cddf9SRui Paulo * Delay EAPOL frame transmission until a 932f05cddf9SRui Paulo * possible WPS STA initiates the handshake 933f05cddf9SRui Paulo * with EAPOL-Start. Only allow the wait to be 934f05cddf9SRui Paulo * skipped if the STA is known to support WPS 935f05cddf9SRui Paulo * 2.0. 936e28a4053SRui Paulo */ 937f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "WPS: Do not start " 938f05cddf9SRui Paulo "EAPOL until EAPOL-Start is " 939f05cddf9SRui Paulo "received"); 940e28a4053SRui Paulo sta->eapol_sm->flags |= EAPOL_SM_WAIT_START; 941e28a4053SRui Paulo } 942f05cddf9SRui Paulo } 943e28a4053SRui Paulo #endif /* CONFIG_WPS */ 944e28a4053SRui Paulo 945e28a4053SRui Paulo sta->eapol_sm->eap_if->portEnabled = TRUE; 946e28a4053SRui Paulo } 947e28a4053SRui Paulo 948e28a4053SRui Paulo /* since we support version 1, we can ignore version field and proceed 949e28a4053SRui Paulo * as specified in version 1 standard [IEEE Std 802.1X-2001, 7.5.5] */ 950e28a4053SRui Paulo /* TODO: actually, we are not version 1 anymore.. However, Version 2 951e28a4053SRui Paulo * does not change frame contents, so should be ok to process frames 952e28a4053SRui Paulo * more or less identically. Some changes might be needed for 953e28a4053SRui Paulo * verification of fields. */ 954e28a4053SRui Paulo 955e28a4053SRui Paulo switch (hdr->type) { 956e28a4053SRui Paulo case IEEE802_1X_TYPE_EAP_PACKET: 957e28a4053SRui Paulo handle_eap(hapd, sta, (u8 *) (hdr + 1), datalen); 958e28a4053SRui Paulo break; 959e28a4053SRui Paulo 960e28a4053SRui Paulo case IEEE802_1X_TYPE_EAPOL_START: 961e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 962e28a4053SRui Paulo HOSTAPD_LEVEL_DEBUG, "received EAPOL-Start " 963e28a4053SRui Paulo "from STA"); 964e28a4053SRui Paulo sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START; 965e28a4053SRui Paulo pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm); 966e28a4053SRui Paulo if (pmksa) { 967e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, 968e28a4053SRui Paulo HOSTAPD_LEVEL_DEBUG, "cached PMKSA " 969e28a4053SRui Paulo "available - ignore it since " 970e28a4053SRui Paulo "STA sent EAPOL-Start"); 971e28a4053SRui Paulo wpa_auth_sta_clear_pmksa(sta->wpa_sm, pmksa); 972e28a4053SRui Paulo } 973e28a4053SRui Paulo sta->eapol_sm->eapolStart = TRUE; 974e28a4053SRui Paulo sta->eapol_sm->dot1xAuthEapolStartFramesRx++; 975f05cddf9SRui Paulo eap_server_clear_identity(sta->eapol_sm->eap); 976e28a4053SRui Paulo wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL); 977e28a4053SRui Paulo break; 978e28a4053SRui Paulo 979e28a4053SRui Paulo case IEEE802_1X_TYPE_EAPOL_LOGOFF: 980e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 981e28a4053SRui Paulo HOSTAPD_LEVEL_DEBUG, "received EAPOL-Logoff " 982e28a4053SRui Paulo "from STA"); 983e28a4053SRui Paulo sta->acct_terminate_cause = 984e28a4053SRui Paulo RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; 985e28a4053SRui Paulo accounting_sta_stop(hapd, sta); 986e28a4053SRui Paulo sta->eapol_sm->eapolLogoff = TRUE; 987e28a4053SRui Paulo sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++; 988f05cddf9SRui Paulo eap_server_clear_identity(sta->eapol_sm->eap); 989e28a4053SRui Paulo break; 990e28a4053SRui Paulo 991e28a4053SRui Paulo case IEEE802_1X_TYPE_EAPOL_KEY: 992e28a4053SRui Paulo wpa_printf(MSG_DEBUG, " EAPOL-Key"); 993f05cddf9SRui Paulo if (!ap_sta_is_authorized(sta)) { 994e28a4053SRui Paulo wpa_printf(MSG_DEBUG, " Dropped key data from " 995e28a4053SRui Paulo "unauthorized Supplicant"); 996e28a4053SRui Paulo break; 997e28a4053SRui Paulo } 998e28a4053SRui Paulo break; 999e28a4053SRui Paulo 1000e28a4053SRui Paulo case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT: 1001e28a4053SRui Paulo wpa_printf(MSG_DEBUG, " EAPOL-Encapsulated-ASF-Alert"); 1002e28a4053SRui Paulo /* TODO: implement support for this; show data */ 1003e28a4053SRui Paulo break; 1004e28a4053SRui Paulo 1005e28a4053SRui Paulo default: 1006e28a4053SRui Paulo wpa_printf(MSG_DEBUG, " unknown IEEE 802.1X packet type"); 1007e28a4053SRui Paulo sta->eapol_sm->dot1xAuthInvalidEapolFramesRx++; 1008e28a4053SRui Paulo break; 1009e28a4053SRui Paulo } 1010e28a4053SRui Paulo 1011e28a4053SRui Paulo eapol_auth_step(sta->eapol_sm); 1012e28a4053SRui Paulo } 1013e28a4053SRui Paulo 1014e28a4053SRui Paulo 1015e28a4053SRui Paulo /** 1016e28a4053SRui Paulo * ieee802_1x_new_station - Start IEEE 802.1X authentication 1017e28a4053SRui Paulo * @hapd: hostapd BSS data 1018e28a4053SRui Paulo * @sta: The station 1019e28a4053SRui Paulo * 1020e28a4053SRui Paulo * This function is called to start IEEE 802.1X authentication when a new 1021e28a4053SRui Paulo * station completes IEEE 802.11 association. 1022e28a4053SRui Paulo */ 1023e28a4053SRui Paulo void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) 1024e28a4053SRui Paulo { 1025e28a4053SRui Paulo struct rsn_pmksa_cache_entry *pmksa; 1026e28a4053SRui Paulo int reassoc = 1; 1027e28a4053SRui Paulo int force_1x = 0; 1028f05cddf9SRui Paulo int key_mgmt; 1029e28a4053SRui Paulo 1030e28a4053SRui Paulo #ifdef CONFIG_WPS 10315b9c547cSRui Paulo if (hapd->conf->wps_state && 10325b9c547cSRui Paulo ((hapd->conf->wpa && (sta->flags & WLAN_STA_MAYBE_WPS)) || 10335b9c547cSRui Paulo (sta->flags & WLAN_STA_WPS))) { 1034e28a4053SRui Paulo /* 1035e28a4053SRui Paulo * Need to enable IEEE 802.1X/EAPOL state machines for possible 1036e28a4053SRui Paulo * WPS handshake even if IEEE 802.1X/EAPOL is not used for 1037e28a4053SRui Paulo * authentication in this BSS. 1038e28a4053SRui Paulo */ 1039e28a4053SRui Paulo force_1x = 1; 1040e28a4053SRui Paulo } 1041e28a4053SRui Paulo #endif /* CONFIG_WPS */ 1042e28a4053SRui Paulo 10435b9c547cSRui Paulo if (!force_1x && !hapd->conf->ieee802_1x && !hapd->conf->osen) { 1044f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - " 1045f05cddf9SRui Paulo "802.1X not enabled or forced for WPS"); 1046f05cddf9SRui Paulo /* 1047f05cddf9SRui Paulo * Clear any possible EAPOL authenticator state to support 1048f05cddf9SRui Paulo * reassociation change from WPS to PSK. 1049f05cddf9SRui Paulo */ 1050f05cddf9SRui Paulo ieee802_1x_free_station(sta); 1051e28a4053SRui Paulo return; 1052f05cddf9SRui Paulo } 1053f05cddf9SRui Paulo 1054f05cddf9SRui Paulo key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm); 1055f05cddf9SRui Paulo if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) { 1056f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - using PSK"); 1057f05cddf9SRui Paulo /* 1058f05cddf9SRui Paulo * Clear any possible EAPOL authenticator state to support 1059f05cddf9SRui Paulo * reassociation change from WPA-EAP to PSK. 1060f05cddf9SRui Paulo */ 1061f05cddf9SRui Paulo ieee802_1x_free_station(sta); 1062f05cddf9SRui Paulo return; 1063f05cddf9SRui Paulo } 1064e28a4053SRui Paulo 1065e28a4053SRui Paulo if (sta->eapol_sm == NULL) { 1066e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 1067e28a4053SRui Paulo HOSTAPD_LEVEL_DEBUG, "start authentication"); 1068e28a4053SRui Paulo sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta); 1069e28a4053SRui Paulo if (sta->eapol_sm == NULL) { 1070e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, 1071e28a4053SRui Paulo HOSTAPD_MODULE_IEEE8021X, 1072e28a4053SRui Paulo HOSTAPD_LEVEL_INFO, 1073e28a4053SRui Paulo "failed to allocate state machine"); 1074e28a4053SRui Paulo return; 1075e28a4053SRui Paulo } 1076e28a4053SRui Paulo reassoc = 0; 1077e28a4053SRui Paulo } 1078e28a4053SRui Paulo 1079e28a4053SRui Paulo #ifdef CONFIG_WPS 1080e28a4053SRui Paulo sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START; 10815b9c547cSRui Paulo if (!hapd->conf->ieee802_1x && hapd->conf->wps_state && 10825b9c547cSRui Paulo !(sta->flags & WLAN_STA_WPS2)) { 1083e28a4053SRui Paulo /* 1084f05cddf9SRui Paulo * Delay EAPOL frame transmission until a possible WPS STA 1085f05cddf9SRui Paulo * initiates the handshake with EAPOL-Start. Only allow the 1086f05cddf9SRui Paulo * wait to be skipped if the STA is known to support WPS 2.0. 1087e28a4053SRui Paulo */ 1088f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "WPS: Do not start EAPOL until " 1089f05cddf9SRui Paulo "EAPOL-Start is received"); 1090e28a4053SRui Paulo sta->eapol_sm->flags |= EAPOL_SM_WAIT_START; 1091e28a4053SRui Paulo } 1092e28a4053SRui Paulo #endif /* CONFIG_WPS */ 1093e28a4053SRui Paulo 1094e28a4053SRui Paulo sta->eapol_sm->eap_if->portEnabled = TRUE; 1095e28a4053SRui Paulo 1096f05cddf9SRui Paulo #ifdef CONFIG_IEEE80211R 1097f05cddf9SRui Paulo if (sta->auth_alg == WLAN_AUTH_FT) { 1098f05cddf9SRui Paulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 1099f05cddf9SRui Paulo HOSTAPD_LEVEL_DEBUG, 1100f05cddf9SRui Paulo "PMK from FT - skip IEEE 802.1X/EAP"); 1101f05cddf9SRui Paulo /* Setup EAPOL state machines to already authenticated state 1102f05cddf9SRui Paulo * because of existing FT information from R0KH. */ 1103f05cddf9SRui Paulo sta->eapol_sm->keyRun = TRUE; 1104f05cddf9SRui Paulo sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; 1105f05cddf9SRui Paulo sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; 1106f05cddf9SRui Paulo sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; 1107f05cddf9SRui Paulo sta->eapol_sm->authSuccess = TRUE; 1108f05cddf9SRui Paulo sta->eapol_sm->authFail = FALSE; 1109f05cddf9SRui Paulo if (sta->eapol_sm->eap) 1110f05cddf9SRui Paulo eap_sm_notify_cached(sta->eapol_sm->eap); 1111f05cddf9SRui Paulo /* TODO: get vlan_id from R0KH using RRB message */ 1112f05cddf9SRui Paulo return; 1113f05cddf9SRui Paulo } 1114f05cddf9SRui Paulo #endif /* CONFIG_IEEE80211R */ 1115f05cddf9SRui Paulo 1116e28a4053SRui Paulo pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm); 1117e28a4053SRui Paulo if (pmksa) { 1118e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 1119e28a4053SRui Paulo HOSTAPD_LEVEL_DEBUG, 1120e28a4053SRui Paulo "PMK from PMKSA cache - skip IEEE 802.1X/EAP"); 1121e28a4053SRui Paulo /* Setup EAPOL state machines to already authenticated state 1122e28a4053SRui Paulo * because of existing PMKSA information in the cache. */ 1123e28a4053SRui Paulo sta->eapol_sm->keyRun = TRUE; 1124e28a4053SRui Paulo sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; 1125e28a4053SRui Paulo sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; 1126e28a4053SRui Paulo sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; 1127e28a4053SRui Paulo sta->eapol_sm->authSuccess = TRUE; 1128f05cddf9SRui Paulo sta->eapol_sm->authFail = FALSE; 1129e28a4053SRui Paulo if (sta->eapol_sm->eap) 1130e28a4053SRui Paulo eap_sm_notify_cached(sta->eapol_sm->eap); 1131e28a4053SRui Paulo pmksa_cache_to_eapol_data(pmksa, sta->eapol_sm); 1132*325151a3SRui Paulo ap_sta_bind_vlan(hapd, sta); 1133e28a4053SRui Paulo } else { 1134e28a4053SRui Paulo if (reassoc) { 1135e28a4053SRui Paulo /* 1136e28a4053SRui Paulo * Force EAPOL state machines to start 1137e28a4053SRui Paulo * re-authentication without having to wait for the 1138e28a4053SRui Paulo * Supplicant to send EAPOL-Start. 1139e28a4053SRui Paulo */ 1140e28a4053SRui Paulo sta->eapol_sm->reAuthenticate = TRUE; 1141e28a4053SRui Paulo } 1142e28a4053SRui Paulo eapol_auth_step(sta->eapol_sm); 1143e28a4053SRui Paulo } 1144e28a4053SRui Paulo } 1145e28a4053SRui Paulo 1146e28a4053SRui Paulo 1147e28a4053SRui Paulo void ieee802_1x_free_station(struct sta_info *sta) 1148e28a4053SRui Paulo { 1149e28a4053SRui Paulo struct eapol_state_machine *sm = sta->eapol_sm; 1150e28a4053SRui Paulo 1151e28a4053SRui Paulo if (sm == NULL) 1152e28a4053SRui Paulo return; 1153e28a4053SRui Paulo 1154e28a4053SRui Paulo sta->eapol_sm = NULL; 1155e28a4053SRui Paulo 1156e28a4053SRui Paulo #ifndef CONFIG_NO_RADIUS 1157e28a4053SRui Paulo radius_msg_free(sm->last_recv_radius); 1158e28a4053SRui Paulo radius_free_class(&sm->radius_class); 1159f05cddf9SRui Paulo wpabuf_free(sm->radius_cui); 1160e28a4053SRui Paulo #endif /* CONFIG_NO_RADIUS */ 1161e28a4053SRui Paulo 1162e28a4053SRui Paulo os_free(sm->identity); 1163e28a4053SRui Paulo eapol_auth_free(sm); 1164e28a4053SRui Paulo } 1165e28a4053SRui Paulo 1166e28a4053SRui Paulo 1167e28a4053SRui Paulo #ifndef CONFIG_NO_RADIUS 1168e28a4053SRui Paulo static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd, 1169e28a4053SRui Paulo struct sta_info *sta) 1170e28a4053SRui Paulo { 1171f05cddf9SRui Paulo struct wpabuf *eap; 1172f05cddf9SRui Paulo const struct eap_hdr *hdr; 1173e28a4053SRui Paulo int eap_type = -1; 1174e28a4053SRui Paulo char buf[64]; 1175e28a4053SRui Paulo struct radius_msg *msg; 1176e28a4053SRui Paulo struct eapol_state_machine *sm = sta->eapol_sm; 1177e28a4053SRui Paulo 1178e28a4053SRui Paulo if (sm == NULL || sm->last_recv_radius == NULL) { 1179e28a4053SRui Paulo if (sm) 1180e28a4053SRui Paulo sm->eap_if->aaaEapNoReq = TRUE; 1181e28a4053SRui Paulo return; 1182e28a4053SRui Paulo } 1183e28a4053SRui Paulo 1184e28a4053SRui Paulo msg = sm->last_recv_radius; 1185e28a4053SRui Paulo 1186f05cddf9SRui Paulo eap = radius_msg_get_eap(msg); 1187e28a4053SRui Paulo if (eap == NULL) { 1188e28a4053SRui Paulo /* RFC 3579, Chap. 2.6.3: 1189e28a4053SRui Paulo * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message 1190e28a4053SRui Paulo * attribute */ 1191e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 1192e28a4053SRui Paulo HOSTAPD_LEVEL_WARNING, "could not extract " 1193e28a4053SRui Paulo "EAP-Message from RADIUS message"); 1194e28a4053SRui Paulo sm->eap_if->aaaEapNoReq = TRUE; 1195e28a4053SRui Paulo return; 1196e28a4053SRui Paulo } 1197e28a4053SRui Paulo 1198f05cddf9SRui Paulo if (wpabuf_len(eap) < sizeof(*hdr)) { 1199e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 1200e28a4053SRui Paulo HOSTAPD_LEVEL_WARNING, "too short EAP packet " 1201e28a4053SRui Paulo "received from authentication server"); 1202f05cddf9SRui Paulo wpabuf_free(eap); 1203e28a4053SRui Paulo sm->eap_if->aaaEapNoReq = TRUE; 1204e28a4053SRui Paulo return; 1205e28a4053SRui Paulo } 1206e28a4053SRui Paulo 1207f05cddf9SRui Paulo if (wpabuf_len(eap) > sizeof(*hdr)) 1208f05cddf9SRui Paulo eap_type = (wpabuf_head_u8(eap))[sizeof(*hdr)]; 1209e28a4053SRui Paulo 1210f05cddf9SRui Paulo hdr = wpabuf_head(eap); 1211e28a4053SRui Paulo switch (hdr->code) { 1212e28a4053SRui Paulo case EAP_CODE_REQUEST: 1213e28a4053SRui Paulo if (eap_type >= 0) 1214e28a4053SRui Paulo sm->eap_type_authsrv = eap_type; 1215e28a4053SRui Paulo os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)", 12165b9c547cSRui Paulo eap_server_get_name(0, eap_type), eap_type); 1217e28a4053SRui Paulo break; 1218e28a4053SRui Paulo case EAP_CODE_RESPONSE: 1219e28a4053SRui Paulo os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)", 12205b9c547cSRui Paulo eap_server_get_name(0, eap_type), eap_type); 1221e28a4053SRui Paulo break; 1222e28a4053SRui Paulo case EAP_CODE_SUCCESS: 1223e28a4053SRui Paulo os_strlcpy(buf, "EAP Success", sizeof(buf)); 1224e28a4053SRui Paulo break; 1225e28a4053SRui Paulo case EAP_CODE_FAILURE: 1226e28a4053SRui Paulo os_strlcpy(buf, "EAP Failure", sizeof(buf)); 1227e28a4053SRui Paulo break; 1228e28a4053SRui Paulo default: 1229e28a4053SRui Paulo os_strlcpy(buf, "unknown EAP code", sizeof(buf)); 1230e28a4053SRui Paulo break; 1231e28a4053SRui Paulo } 1232e28a4053SRui Paulo buf[sizeof(buf) - 1] = '\0'; 1233e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 1234e28a4053SRui Paulo HOSTAPD_LEVEL_DEBUG, "decapsulated EAP packet (code=%d " 1235e28a4053SRui Paulo "id=%d len=%d) from RADIUS server: %s", 1236e28a4053SRui Paulo hdr->code, hdr->identifier, be_to_host16(hdr->length), 1237e28a4053SRui Paulo buf); 1238e28a4053SRui Paulo sm->eap_if->aaaEapReq = TRUE; 1239e28a4053SRui Paulo 1240e28a4053SRui Paulo wpabuf_free(sm->eap_if->aaaEapReqData); 1241f05cddf9SRui Paulo sm->eap_if->aaaEapReqData = eap; 1242e28a4053SRui Paulo } 1243e28a4053SRui Paulo 1244e28a4053SRui Paulo 1245e28a4053SRui Paulo static void ieee802_1x_get_keys(struct hostapd_data *hapd, 1246e28a4053SRui Paulo struct sta_info *sta, struct radius_msg *msg, 1247e28a4053SRui Paulo struct radius_msg *req, 1248e28a4053SRui Paulo const u8 *shared_secret, 1249e28a4053SRui Paulo size_t shared_secret_len) 1250e28a4053SRui Paulo { 1251e28a4053SRui Paulo struct radius_ms_mppe_keys *keys; 1252e28a4053SRui Paulo struct eapol_state_machine *sm = sta->eapol_sm; 1253e28a4053SRui Paulo if (sm == NULL) 1254e28a4053SRui Paulo return; 1255e28a4053SRui Paulo 1256e28a4053SRui Paulo keys = radius_msg_get_ms_keys(msg, req, shared_secret, 1257e28a4053SRui Paulo shared_secret_len); 1258e28a4053SRui Paulo 1259e28a4053SRui Paulo if (keys && keys->send && keys->recv) { 1260e28a4053SRui Paulo size_t len = keys->send_len + keys->recv_len; 1261e28a4053SRui Paulo wpa_hexdump_key(MSG_DEBUG, "MS-MPPE-Send-Key", 1262e28a4053SRui Paulo keys->send, keys->send_len); 1263e28a4053SRui Paulo wpa_hexdump_key(MSG_DEBUG, "MS-MPPE-Recv-Key", 1264e28a4053SRui Paulo keys->recv, keys->recv_len); 1265e28a4053SRui Paulo 1266e28a4053SRui Paulo os_free(sm->eap_if->aaaEapKeyData); 1267e28a4053SRui Paulo sm->eap_if->aaaEapKeyData = os_malloc(len); 1268e28a4053SRui Paulo if (sm->eap_if->aaaEapKeyData) { 1269e28a4053SRui Paulo os_memcpy(sm->eap_if->aaaEapKeyData, keys->recv, 1270e28a4053SRui Paulo keys->recv_len); 1271e28a4053SRui Paulo os_memcpy(sm->eap_if->aaaEapKeyData + keys->recv_len, 1272e28a4053SRui Paulo keys->send, keys->send_len); 1273e28a4053SRui Paulo sm->eap_if->aaaEapKeyDataLen = len; 1274e28a4053SRui Paulo sm->eap_if->aaaEapKeyAvailable = TRUE; 1275e28a4053SRui Paulo } 12765b9c547cSRui Paulo } else { 12775b9c547cSRui Paulo wpa_printf(MSG_DEBUG, 12785b9c547cSRui Paulo "MS-MPPE: 1x_get_keys, could not get keys: %p send: %p recv: %p", 12795b9c547cSRui Paulo keys, keys ? keys->send : NULL, 12805b9c547cSRui Paulo keys ? keys->recv : NULL); 1281e28a4053SRui Paulo } 1282e28a4053SRui Paulo 1283e28a4053SRui Paulo if (keys) { 1284e28a4053SRui Paulo os_free(keys->send); 1285e28a4053SRui Paulo os_free(keys->recv); 1286e28a4053SRui Paulo os_free(keys); 1287e28a4053SRui Paulo } 1288e28a4053SRui Paulo } 1289e28a4053SRui Paulo 1290e28a4053SRui Paulo 1291e28a4053SRui Paulo static void ieee802_1x_store_radius_class(struct hostapd_data *hapd, 1292e28a4053SRui Paulo struct sta_info *sta, 1293e28a4053SRui Paulo struct radius_msg *msg) 1294e28a4053SRui Paulo { 1295*325151a3SRui Paulo u8 *attr_class; 1296e28a4053SRui Paulo size_t class_len; 1297e28a4053SRui Paulo struct eapol_state_machine *sm = sta->eapol_sm; 1298e28a4053SRui Paulo int count, i; 1299e28a4053SRui Paulo struct radius_attr_data *nclass; 1300e28a4053SRui Paulo size_t nclass_count; 1301e28a4053SRui Paulo 1302e28a4053SRui Paulo if (!hapd->conf->radius->acct_server || hapd->radius == NULL || 1303e28a4053SRui Paulo sm == NULL) 1304e28a4053SRui Paulo return; 1305e28a4053SRui Paulo 1306e28a4053SRui Paulo radius_free_class(&sm->radius_class); 1307e28a4053SRui Paulo count = radius_msg_count_attr(msg, RADIUS_ATTR_CLASS, 1); 1308e28a4053SRui Paulo if (count <= 0) 1309e28a4053SRui Paulo return; 1310e28a4053SRui Paulo 1311f05cddf9SRui Paulo nclass = os_calloc(count, sizeof(struct radius_attr_data)); 1312e28a4053SRui Paulo if (nclass == NULL) 1313e28a4053SRui Paulo return; 1314e28a4053SRui Paulo 1315e28a4053SRui Paulo nclass_count = 0; 1316e28a4053SRui Paulo 1317*325151a3SRui Paulo attr_class = NULL; 1318e28a4053SRui Paulo for (i = 0; i < count; i++) { 1319e28a4053SRui Paulo do { 1320e28a4053SRui Paulo if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CLASS, 1321*325151a3SRui Paulo &attr_class, &class_len, 1322*325151a3SRui Paulo attr_class) < 0) { 1323e28a4053SRui Paulo i = count; 1324e28a4053SRui Paulo break; 1325e28a4053SRui Paulo } 1326e28a4053SRui Paulo } while (class_len < 1); 1327e28a4053SRui Paulo 1328e28a4053SRui Paulo nclass[nclass_count].data = os_malloc(class_len); 1329e28a4053SRui Paulo if (nclass[nclass_count].data == NULL) 1330e28a4053SRui Paulo break; 1331e28a4053SRui Paulo 1332*325151a3SRui Paulo os_memcpy(nclass[nclass_count].data, attr_class, class_len); 1333e28a4053SRui Paulo nclass[nclass_count].len = class_len; 1334e28a4053SRui Paulo nclass_count++; 1335e28a4053SRui Paulo } 1336e28a4053SRui Paulo 1337e28a4053SRui Paulo sm->radius_class.attr = nclass; 1338e28a4053SRui Paulo sm->radius_class.count = nclass_count; 1339e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "IEEE 802.1X: Stored %lu RADIUS Class " 1340e28a4053SRui Paulo "attributes for " MACSTR, 1341e28a4053SRui Paulo (unsigned long) sm->radius_class.count, 1342e28a4053SRui Paulo MAC2STR(sta->addr)); 1343e28a4053SRui Paulo } 1344e28a4053SRui Paulo 1345e28a4053SRui Paulo 1346e28a4053SRui Paulo /* Update sta->identity based on User-Name attribute in Access-Accept */ 1347e28a4053SRui Paulo static void ieee802_1x_update_sta_identity(struct hostapd_data *hapd, 1348e28a4053SRui Paulo struct sta_info *sta, 1349e28a4053SRui Paulo struct radius_msg *msg) 1350e28a4053SRui Paulo { 1351e28a4053SRui Paulo u8 *buf, *identity; 1352e28a4053SRui Paulo size_t len; 1353e28a4053SRui Paulo struct eapol_state_machine *sm = sta->eapol_sm; 1354e28a4053SRui Paulo 1355e28a4053SRui Paulo if (sm == NULL) 1356e28a4053SRui Paulo return; 1357e28a4053SRui Paulo 1358e28a4053SRui Paulo if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, &buf, &len, 1359e28a4053SRui Paulo NULL) < 0) 1360e28a4053SRui Paulo return; 1361e28a4053SRui Paulo 13625b9c547cSRui Paulo identity = (u8 *) dup_binstr(buf, len); 1363e28a4053SRui Paulo if (identity == NULL) 1364e28a4053SRui Paulo return; 1365e28a4053SRui Paulo 1366e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 1367e28a4053SRui Paulo HOSTAPD_LEVEL_DEBUG, "old identity '%s' updated with " 1368e28a4053SRui Paulo "User-Name from Access-Accept '%s'", 1369e28a4053SRui Paulo sm->identity ? (char *) sm->identity : "N/A", 1370e28a4053SRui Paulo (char *) identity); 1371e28a4053SRui Paulo 1372e28a4053SRui Paulo os_free(sm->identity); 1373e28a4053SRui Paulo sm->identity = identity; 1374e28a4053SRui Paulo sm->identity_len = len; 1375e28a4053SRui Paulo } 1376e28a4053SRui Paulo 1377e28a4053SRui Paulo 1378f05cddf9SRui Paulo /* Update CUI based on Chargeable-User-Identity attribute in Access-Accept */ 1379f05cddf9SRui Paulo static void ieee802_1x_update_sta_cui(struct hostapd_data *hapd, 1380f05cddf9SRui Paulo struct sta_info *sta, 1381f05cddf9SRui Paulo struct radius_msg *msg) 1382f05cddf9SRui Paulo { 1383f05cddf9SRui Paulo struct eapol_state_machine *sm = sta->eapol_sm; 1384f05cddf9SRui Paulo struct wpabuf *cui; 1385f05cddf9SRui Paulo u8 *buf; 1386f05cddf9SRui Paulo size_t len; 1387f05cddf9SRui Paulo 1388f05cddf9SRui Paulo if (sm == NULL) 1389f05cddf9SRui Paulo return; 1390f05cddf9SRui Paulo 1391f05cddf9SRui Paulo if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, 1392f05cddf9SRui Paulo &buf, &len, NULL) < 0) 1393f05cddf9SRui Paulo return; 1394f05cddf9SRui Paulo 1395f05cddf9SRui Paulo cui = wpabuf_alloc_copy(buf, len); 1396f05cddf9SRui Paulo if (cui == NULL) 1397f05cddf9SRui Paulo return; 1398f05cddf9SRui Paulo 1399f05cddf9SRui Paulo wpabuf_free(sm->radius_cui); 1400f05cddf9SRui Paulo sm->radius_cui = cui; 1401f05cddf9SRui Paulo } 1402f05cddf9SRui Paulo 1403f05cddf9SRui Paulo 14045b9c547cSRui Paulo #ifdef CONFIG_HS20 14055b9c547cSRui Paulo 14065b9c547cSRui Paulo static void ieee802_1x_hs20_sub_rem(struct sta_info *sta, u8 *pos, size_t len) 14075b9c547cSRui Paulo { 14085b9c547cSRui Paulo sta->remediation = 1; 14095b9c547cSRui Paulo os_free(sta->remediation_url); 14105b9c547cSRui Paulo if (len > 2) { 14115b9c547cSRui Paulo sta->remediation_url = os_malloc(len); 14125b9c547cSRui Paulo if (!sta->remediation_url) 14135b9c547cSRui Paulo return; 14145b9c547cSRui Paulo sta->remediation_method = pos[0]; 14155b9c547cSRui Paulo os_memcpy(sta->remediation_url, pos + 1, len - 1); 14165b9c547cSRui Paulo sta->remediation_url[len - 1] = '\0'; 14175b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "HS 2.0: Subscription remediation needed " 14185b9c547cSRui Paulo "for " MACSTR " - server method %u URL %s", 14195b9c547cSRui Paulo MAC2STR(sta->addr), sta->remediation_method, 14205b9c547cSRui Paulo sta->remediation_url); 14215b9c547cSRui Paulo } else { 14225b9c547cSRui Paulo sta->remediation_url = NULL; 14235b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "HS 2.0: Subscription remediation needed " 14245b9c547cSRui Paulo "for " MACSTR, MAC2STR(sta->addr)); 14255b9c547cSRui Paulo } 14265b9c547cSRui Paulo /* TODO: assign the STA into remediation VLAN or add filtering */ 14275b9c547cSRui Paulo } 14285b9c547cSRui Paulo 14295b9c547cSRui Paulo 14305b9c547cSRui Paulo static void ieee802_1x_hs20_deauth_req(struct hostapd_data *hapd, 14315b9c547cSRui Paulo struct sta_info *sta, u8 *pos, 14325b9c547cSRui Paulo size_t len) 14335b9c547cSRui Paulo { 14345b9c547cSRui Paulo if (len < 3) 14355b9c547cSRui Paulo return; /* Malformed information */ 14365b9c547cSRui Paulo sta->hs20_deauth_requested = 1; 14375b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "HS 2.0: Deauthentication request - Code %u " 14385b9c547cSRui Paulo "Re-auth Delay %u", 14395b9c547cSRui Paulo *pos, WPA_GET_LE16(pos + 1)); 14405b9c547cSRui Paulo wpabuf_free(sta->hs20_deauth_req); 14415b9c547cSRui Paulo sta->hs20_deauth_req = wpabuf_alloc(len + 1); 14425b9c547cSRui Paulo if (sta->hs20_deauth_req) { 14435b9c547cSRui Paulo wpabuf_put_data(sta->hs20_deauth_req, pos, 3); 14445b9c547cSRui Paulo wpabuf_put_u8(sta->hs20_deauth_req, len - 3); 14455b9c547cSRui Paulo wpabuf_put_data(sta->hs20_deauth_req, pos + 3, len - 3); 14465b9c547cSRui Paulo } 14475b9c547cSRui Paulo ap_sta_session_timeout(hapd, sta, hapd->conf->hs20_deauth_req_timeout); 14485b9c547cSRui Paulo } 14495b9c547cSRui Paulo 14505b9c547cSRui Paulo 14515b9c547cSRui Paulo static void ieee802_1x_hs20_session_info(struct hostapd_data *hapd, 14525b9c547cSRui Paulo struct sta_info *sta, u8 *pos, 14535b9c547cSRui Paulo size_t len, int session_timeout) 14545b9c547cSRui Paulo { 14555b9c547cSRui Paulo unsigned int swt; 14565b9c547cSRui Paulo int warning_time, beacon_int; 14575b9c547cSRui Paulo 14585b9c547cSRui Paulo if (len < 1) 14595b9c547cSRui Paulo return; /* Malformed information */ 14605b9c547cSRui Paulo os_free(sta->hs20_session_info_url); 14615b9c547cSRui Paulo sta->hs20_session_info_url = os_malloc(len); 14625b9c547cSRui Paulo if (sta->hs20_session_info_url == NULL) 14635b9c547cSRui Paulo return; 14645b9c547cSRui Paulo swt = pos[0]; 14655b9c547cSRui Paulo os_memcpy(sta->hs20_session_info_url, pos + 1, len - 1); 14665b9c547cSRui Paulo sta->hs20_session_info_url[len - 1] = '\0'; 14675b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "HS 2.0: Session Information URL='%s' SWT=%u " 14685b9c547cSRui Paulo "(session_timeout=%d)", 14695b9c547cSRui Paulo sta->hs20_session_info_url, swt, session_timeout); 14705b9c547cSRui Paulo if (session_timeout < 0) { 14715b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "HS 2.0: No Session-Timeout set - ignore session info URL"); 14725b9c547cSRui Paulo return; 14735b9c547cSRui Paulo } 14745b9c547cSRui Paulo if (swt == 255) 14755b9c547cSRui Paulo swt = 1; /* Use one minute as the AP selected value */ 14765b9c547cSRui Paulo 14775b9c547cSRui Paulo if ((unsigned int) session_timeout < swt * 60) 14785b9c547cSRui Paulo warning_time = 0; 14795b9c547cSRui Paulo else 14805b9c547cSRui Paulo warning_time = session_timeout - swt * 60; 14815b9c547cSRui Paulo 14825b9c547cSRui Paulo beacon_int = hapd->iconf->beacon_int; 14835b9c547cSRui Paulo if (beacon_int < 1) 14845b9c547cSRui Paulo beacon_int = 100; /* best guess */ 14855b9c547cSRui Paulo sta->hs20_disassoc_timer = swt * 60 * 1000 / beacon_int * 125 / 128; 14865b9c547cSRui Paulo if (sta->hs20_disassoc_timer > 65535) 14875b9c547cSRui Paulo sta->hs20_disassoc_timer = 65535; 14885b9c547cSRui Paulo 14895b9c547cSRui Paulo ap_sta_session_warning_timeout(hapd, sta, warning_time); 14905b9c547cSRui Paulo } 14915b9c547cSRui Paulo 14925b9c547cSRui Paulo #endif /* CONFIG_HS20 */ 14935b9c547cSRui Paulo 14945b9c547cSRui Paulo 14955b9c547cSRui Paulo static void ieee802_1x_check_hs20(struct hostapd_data *hapd, 14965b9c547cSRui Paulo struct sta_info *sta, 14975b9c547cSRui Paulo struct radius_msg *msg, 14985b9c547cSRui Paulo int session_timeout) 14995b9c547cSRui Paulo { 15005b9c547cSRui Paulo #ifdef CONFIG_HS20 15015b9c547cSRui Paulo u8 *buf, *pos, *end, type, sublen; 15025b9c547cSRui Paulo size_t len; 15035b9c547cSRui Paulo 15045b9c547cSRui Paulo buf = NULL; 15055b9c547cSRui Paulo sta->remediation = 0; 15065b9c547cSRui Paulo sta->hs20_deauth_requested = 0; 15075b9c547cSRui Paulo 15085b9c547cSRui Paulo for (;;) { 15095b9c547cSRui Paulo if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_VENDOR_SPECIFIC, 15105b9c547cSRui Paulo &buf, &len, buf) < 0) 15115b9c547cSRui Paulo break; 15125b9c547cSRui Paulo if (len < 6) 15135b9c547cSRui Paulo continue; 15145b9c547cSRui Paulo pos = buf; 15155b9c547cSRui Paulo end = buf + len; 15165b9c547cSRui Paulo if (WPA_GET_BE32(pos) != RADIUS_VENDOR_ID_WFA) 15175b9c547cSRui Paulo continue; 15185b9c547cSRui Paulo pos += 4; 15195b9c547cSRui Paulo 15205b9c547cSRui Paulo type = *pos++; 15215b9c547cSRui Paulo sublen = *pos++; 15225b9c547cSRui Paulo if (sublen < 2) 15235b9c547cSRui Paulo continue; /* invalid length */ 15245b9c547cSRui Paulo sublen -= 2; /* skip header */ 15255b9c547cSRui Paulo if (pos + sublen > end) 15265b9c547cSRui Paulo continue; /* invalid WFA VSA */ 15275b9c547cSRui Paulo 15285b9c547cSRui Paulo switch (type) { 15295b9c547cSRui Paulo case RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION: 15305b9c547cSRui Paulo ieee802_1x_hs20_sub_rem(sta, pos, sublen); 15315b9c547cSRui Paulo break; 15325b9c547cSRui Paulo case RADIUS_VENDOR_ATTR_WFA_HS20_DEAUTH_REQ: 15335b9c547cSRui Paulo ieee802_1x_hs20_deauth_req(hapd, sta, pos, sublen); 15345b9c547cSRui Paulo break; 15355b9c547cSRui Paulo case RADIUS_VENDOR_ATTR_WFA_HS20_SESSION_INFO_URL: 15365b9c547cSRui Paulo ieee802_1x_hs20_session_info(hapd, sta, pos, sublen, 15375b9c547cSRui Paulo session_timeout); 15385b9c547cSRui Paulo break; 15395b9c547cSRui Paulo } 15405b9c547cSRui Paulo } 15415b9c547cSRui Paulo #endif /* CONFIG_HS20 */ 15425b9c547cSRui Paulo } 15435b9c547cSRui Paulo 15445b9c547cSRui Paulo 1545e28a4053SRui Paulo struct sta_id_search { 1546e28a4053SRui Paulo u8 identifier; 1547e28a4053SRui Paulo struct eapol_state_machine *sm; 1548e28a4053SRui Paulo }; 1549e28a4053SRui Paulo 1550e28a4053SRui Paulo 1551e28a4053SRui Paulo static int ieee802_1x_select_radius_identifier(struct hostapd_data *hapd, 1552e28a4053SRui Paulo struct sta_info *sta, 1553e28a4053SRui Paulo void *ctx) 1554e28a4053SRui Paulo { 1555e28a4053SRui Paulo struct sta_id_search *id_search = ctx; 1556e28a4053SRui Paulo struct eapol_state_machine *sm = sta->eapol_sm; 1557e28a4053SRui Paulo 1558e28a4053SRui Paulo if (sm && sm->radius_identifier >= 0 && 1559e28a4053SRui Paulo sm->radius_identifier == id_search->identifier) { 1560e28a4053SRui Paulo id_search->sm = sm; 1561e28a4053SRui Paulo return 1; 1562e28a4053SRui Paulo } 1563e28a4053SRui Paulo return 0; 1564e28a4053SRui Paulo } 1565e28a4053SRui Paulo 1566e28a4053SRui Paulo 1567e28a4053SRui Paulo static struct eapol_state_machine * 1568e28a4053SRui Paulo ieee802_1x_search_radius_identifier(struct hostapd_data *hapd, u8 identifier) 1569e28a4053SRui Paulo { 1570e28a4053SRui Paulo struct sta_id_search id_search; 1571e28a4053SRui Paulo id_search.identifier = identifier; 1572e28a4053SRui Paulo id_search.sm = NULL; 1573e28a4053SRui Paulo ap_for_each_sta(hapd, ieee802_1x_select_radius_identifier, &id_search); 1574e28a4053SRui Paulo return id_search.sm; 1575e28a4053SRui Paulo } 1576e28a4053SRui Paulo 1577e28a4053SRui Paulo 1578e28a4053SRui Paulo /** 1579e28a4053SRui Paulo * ieee802_1x_receive_auth - Process RADIUS frames from Authentication Server 1580e28a4053SRui Paulo * @msg: RADIUS response message 1581e28a4053SRui Paulo * @req: RADIUS request message 1582e28a4053SRui Paulo * @shared_secret: RADIUS shared secret 1583e28a4053SRui Paulo * @shared_secret_len: Length of shared_secret in octets 1584e28a4053SRui Paulo * @data: Context data (struct hostapd_data *) 1585e28a4053SRui Paulo * Returns: Processing status 1586e28a4053SRui Paulo */ 1587e28a4053SRui Paulo static RadiusRxResult 1588e28a4053SRui Paulo ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, 1589e28a4053SRui Paulo const u8 *shared_secret, size_t shared_secret_len, 1590e28a4053SRui Paulo void *data) 1591e28a4053SRui Paulo { 1592e28a4053SRui Paulo struct hostapd_data *hapd = data; 1593e28a4053SRui Paulo struct sta_info *sta; 1594e28a4053SRui Paulo u32 session_timeout = 0, termination_action, acct_interim_interval; 1595*325151a3SRui Paulo int session_timeout_set, vlan_id = 0; 1596e28a4053SRui Paulo struct eapol_state_machine *sm; 1597e28a4053SRui Paulo int override_eapReq = 0; 1598e28a4053SRui Paulo struct radius_hdr *hdr = radius_msg_get_hdr(msg); 1599e28a4053SRui Paulo 1600e28a4053SRui Paulo sm = ieee802_1x_search_radius_identifier(hapd, hdr->identifier); 1601e28a4053SRui Paulo if (sm == NULL) { 1602e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "IEEE 802.1X: Could not find matching " 1603e28a4053SRui Paulo "station for this RADIUS message"); 1604e28a4053SRui Paulo return RADIUS_RX_UNKNOWN; 1605e28a4053SRui Paulo } 1606e28a4053SRui Paulo sta = sm->sta; 1607e28a4053SRui Paulo 1608e28a4053SRui Paulo /* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be 1609e28a4053SRui Paulo * present when packet contains an EAP-Message attribute */ 1610e28a4053SRui Paulo if (hdr->code == RADIUS_CODE_ACCESS_REJECT && 1611e28a4053SRui Paulo radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL, 1612e28a4053SRui Paulo 0) < 0 && 1613e28a4053SRui Paulo radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) { 1614e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "Allowing RADIUS Access-Reject without " 1615e28a4053SRui Paulo "Message-Authenticator since it does not include " 1616e28a4053SRui Paulo "EAP-Message"); 1617e28a4053SRui Paulo } else if (radius_msg_verify(msg, shared_secret, shared_secret_len, 1618e28a4053SRui Paulo req, 1)) { 16195b9c547cSRui Paulo wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have correct Message-Authenticator - dropped"); 1620e28a4053SRui Paulo return RADIUS_RX_INVALID_AUTHENTICATOR; 1621e28a4053SRui Paulo } 1622e28a4053SRui Paulo 1623e28a4053SRui Paulo if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT && 1624e28a4053SRui Paulo hdr->code != RADIUS_CODE_ACCESS_REJECT && 1625e28a4053SRui Paulo hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) { 16265b9c547cSRui Paulo wpa_printf(MSG_INFO, "Unknown RADIUS message code"); 1627e28a4053SRui Paulo return RADIUS_RX_UNKNOWN; 1628e28a4053SRui Paulo } 1629e28a4053SRui Paulo 1630e28a4053SRui Paulo sm->radius_identifier = -1; 1631e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "RADIUS packet matching with station " MACSTR, 1632e28a4053SRui Paulo MAC2STR(sta->addr)); 1633e28a4053SRui Paulo 1634e28a4053SRui Paulo radius_msg_free(sm->last_recv_radius); 1635e28a4053SRui Paulo sm->last_recv_radius = msg; 1636e28a4053SRui Paulo 1637e28a4053SRui Paulo session_timeout_set = 1638e28a4053SRui Paulo !radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, 1639e28a4053SRui Paulo &session_timeout); 1640e28a4053SRui Paulo if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_TERMINATION_ACTION, 1641e28a4053SRui Paulo &termination_action)) 1642e28a4053SRui Paulo termination_action = RADIUS_TERMINATION_ACTION_DEFAULT; 1643e28a4053SRui Paulo 1644e28a4053SRui Paulo if (hapd->conf->acct_interim_interval == 0 && 1645e28a4053SRui Paulo hdr->code == RADIUS_CODE_ACCESS_ACCEPT && 1646e28a4053SRui Paulo radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL, 1647e28a4053SRui Paulo &acct_interim_interval) == 0) { 1648e28a4053SRui Paulo if (acct_interim_interval < 60) { 1649e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, 1650e28a4053SRui Paulo HOSTAPD_MODULE_IEEE8021X, 1651e28a4053SRui Paulo HOSTAPD_LEVEL_INFO, 1652e28a4053SRui Paulo "ignored too small " 1653e28a4053SRui Paulo "Acct-Interim-Interval %d", 1654e28a4053SRui Paulo acct_interim_interval); 1655e28a4053SRui Paulo } else 1656e28a4053SRui Paulo sta->acct_interim_interval = acct_interim_interval; 1657e28a4053SRui Paulo } 1658e28a4053SRui Paulo 1659e28a4053SRui Paulo 1660e28a4053SRui Paulo switch (hdr->code) { 1661e28a4053SRui Paulo case RADIUS_CODE_ACCESS_ACCEPT: 1662*325151a3SRui Paulo if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED) 1663*325151a3SRui Paulo vlan_id = 0; 1664e28a4053SRui Paulo #ifndef CONFIG_NO_VLAN 1665*325151a3SRui Paulo else 1666*325151a3SRui Paulo vlan_id = radius_msg_get_vlanid(msg); 1667*325151a3SRui Paulo if (vlan_id > 0 && 1668*325151a3SRui Paulo hostapd_vlan_id_valid(hapd->conf->vlan, vlan_id)) { 1669e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, 1670e28a4053SRui Paulo HOSTAPD_MODULE_RADIUS, 1671e28a4053SRui Paulo HOSTAPD_LEVEL_INFO, 1672*325151a3SRui Paulo "VLAN ID %d", vlan_id); 1673*325151a3SRui Paulo } else if (vlan_id > 0) { 1674*325151a3SRui Paulo sta->eapol_sm->authFail = TRUE; 1675*325151a3SRui Paulo hostapd_logger(hapd, sta->addr, 1676*325151a3SRui Paulo HOSTAPD_MODULE_RADIUS, 1677*325151a3SRui Paulo HOSTAPD_LEVEL_INFO, 1678*325151a3SRui Paulo "Invalid VLAN ID %d received from RADIUS server", 1679*325151a3SRui Paulo vlan_id); 1680*325151a3SRui Paulo break; 1681*325151a3SRui Paulo } else if (hapd->conf->ssid.dynamic_vlan == 1682*325151a3SRui Paulo DYNAMIC_VLAN_REQUIRED) { 1683e28a4053SRui Paulo sta->eapol_sm->authFail = TRUE; 1684e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, 1685e28a4053SRui Paulo HOSTAPD_MODULE_IEEE8021X, 1686e28a4053SRui Paulo HOSTAPD_LEVEL_INFO, "authentication " 1687e28a4053SRui Paulo "server did not include required VLAN " 1688e28a4053SRui Paulo "ID in Access-Accept"); 1689e28a4053SRui Paulo break; 1690e28a4053SRui Paulo } 1691e28a4053SRui Paulo #endif /* CONFIG_NO_VLAN */ 1692e28a4053SRui Paulo 1693*325151a3SRui Paulo sta->vlan_id = vlan_id; 1694*325151a3SRui Paulo if ((sta->flags & WLAN_STA_ASSOC) && 1695*325151a3SRui Paulo ap_sta_bind_vlan(hapd, sta) < 0) 1696e28a4053SRui Paulo break; 1697e28a4053SRui Paulo 16985b9c547cSRui Paulo sta->session_timeout_set = !!session_timeout_set; 16995b9c547cSRui Paulo sta->session_timeout = session_timeout; 17005b9c547cSRui Paulo 1701e28a4053SRui Paulo /* RFC 3580, Ch. 3.17 */ 1702e28a4053SRui Paulo if (session_timeout_set && termination_action == 1703e28a4053SRui Paulo RADIUS_TERMINATION_ACTION_RADIUS_REQUEST) { 1704e28a4053SRui Paulo sm->reAuthPeriod = session_timeout; 1705e28a4053SRui Paulo } else if (session_timeout_set) 1706e28a4053SRui Paulo ap_sta_session_timeout(hapd, sta, session_timeout); 1707e28a4053SRui Paulo 1708e28a4053SRui Paulo sm->eap_if->aaaSuccess = TRUE; 1709e28a4053SRui Paulo override_eapReq = 1; 1710e28a4053SRui Paulo ieee802_1x_get_keys(hapd, sta, msg, req, shared_secret, 1711e28a4053SRui Paulo shared_secret_len); 1712e28a4053SRui Paulo ieee802_1x_store_radius_class(hapd, sta, msg); 1713e28a4053SRui Paulo ieee802_1x_update_sta_identity(hapd, sta, msg); 1714f05cddf9SRui Paulo ieee802_1x_update_sta_cui(hapd, sta, msg); 17155b9c547cSRui Paulo ieee802_1x_check_hs20(hapd, sta, msg, 17165b9c547cSRui Paulo session_timeout_set ? 17175b9c547cSRui Paulo (int) session_timeout : -1); 17185b9c547cSRui Paulo if (sm->eap_if->eapKeyAvailable && !sta->remediation && 17195b9c547cSRui Paulo !sta->hs20_deauth_requested && 1720e28a4053SRui Paulo wpa_auth_pmksa_add(sta->wpa_sm, sm->eapol_key_crypt, 1721e28a4053SRui Paulo session_timeout_set ? 1722e28a4053SRui Paulo (int) session_timeout : -1, sm) == 0) { 1723e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, 1724e28a4053SRui Paulo HOSTAPD_LEVEL_DEBUG, 1725e28a4053SRui Paulo "Added PMKSA cache entry"); 1726e28a4053SRui Paulo } 1727e28a4053SRui Paulo break; 1728e28a4053SRui Paulo case RADIUS_CODE_ACCESS_REJECT: 1729e28a4053SRui Paulo sm->eap_if->aaaFail = TRUE; 1730e28a4053SRui Paulo override_eapReq = 1; 1731e28a4053SRui Paulo break; 1732e28a4053SRui Paulo case RADIUS_CODE_ACCESS_CHALLENGE: 1733e28a4053SRui Paulo sm->eap_if->aaaEapReq = TRUE; 1734e28a4053SRui Paulo if (session_timeout_set) { 1735e28a4053SRui Paulo /* RFC 2869, Ch. 2.3.2; RFC 3580, Ch. 3.17 */ 1736e28a4053SRui Paulo sm->eap_if->aaaMethodTimeout = session_timeout; 1737e28a4053SRui Paulo hostapd_logger(hapd, sm->addr, 1738e28a4053SRui Paulo HOSTAPD_MODULE_IEEE8021X, 1739e28a4053SRui Paulo HOSTAPD_LEVEL_DEBUG, 1740e28a4053SRui Paulo "using EAP timeout of %d seconds (from " 1741e28a4053SRui Paulo "RADIUS)", 1742e28a4053SRui Paulo sm->eap_if->aaaMethodTimeout); 1743e28a4053SRui Paulo } else { 1744e28a4053SRui Paulo /* 1745e28a4053SRui Paulo * Use dynamic retransmission behavior per EAP 1746e28a4053SRui Paulo * specification. 1747e28a4053SRui Paulo */ 1748e28a4053SRui Paulo sm->eap_if->aaaMethodTimeout = 0; 1749e28a4053SRui Paulo } 1750e28a4053SRui Paulo break; 1751e28a4053SRui Paulo } 1752e28a4053SRui Paulo 1753e28a4053SRui Paulo ieee802_1x_decapsulate_radius(hapd, sta); 1754e28a4053SRui Paulo if (override_eapReq) 1755e28a4053SRui Paulo sm->eap_if->aaaEapReq = FALSE; 1756e28a4053SRui Paulo 1757e28a4053SRui Paulo eapol_auth_step(sm); 1758e28a4053SRui Paulo 1759e28a4053SRui Paulo return RADIUS_RX_QUEUED; 1760e28a4053SRui Paulo } 1761e28a4053SRui Paulo #endif /* CONFIG_NO_RADIUS */ 1762e28a4053SRui Paulo 1763e28a4053SRui Paulo 1764e28a4053SRui Paulo void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta) 1765e28a4053SRui Paulo { 1766e28a4053SRui Paulo struct eapol_state_machine *sm = sta->eapol_sm; 1767e28a4053SRui Paulo if (sm == NULL) 1768e28a4053SRui Paulo return; 1769e28a4053SRui Paulo 1770e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 1771e28a4053SRui Paulo HOSTAPD_LEVEL_DEBUG, "aborting authentication"); 1772e28a4053SRui Paulo 1773e28a4053SRui Paulo #ifndef CONFIG_NO_RADIUS 1774e28a4053SRui Paulo radius_msg_free(sm->last_recv_radius); 1775e28a4053SRui Paulo sm->last_recv_radius = NULL; 1776e28a4053SRui Paulo #endif /* CONFIG_NO_RADIUS */ 1777e28a4053SRui Paulo 1778e28a4053SRui Paulo if (sm->eap_if->eapTimeout) { 1779e28a4053SRui Paulo /* 1780e28a4053SRui Paulo * Disconnect the STA since it did not reply to the last EAP 1781e28a4053SRui Paulo * request and we cannot continue EAP processing (EAP-Failure 1782e28a4053SRui Paulo * could only be sent if the EAP peer actually replied). 1783e28a4053SRui Paulo */ 1784f05cddf9SRui Paulo wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "EAP Timeout, STA " MACSTR, 1785f05cddf9SRui Paulo MAC2STR(sta->addr)); 1786f05cddf9SRui Paulo 1787e28a4053SRui Paulo sm->eap_if->portEnabled = FALSE; 1788e28a4053SRui Paulo ap_sta_disconnect(hapd, sta, sta->addr, 1789e28a4053SRui Paulo WLAN_REASON_PREV_AUTH_NOT_VALID); 1790e28a4053SRui Paulo } 1791e28a4053SRui Paulo } 1792e28a4053SRui Paulo 1793e28a4053SRui Paulo 1794e28a4053SRui Paulo static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd) 1795e28a4053SRui Paulo { 1796e28a4053SRui Paulo struct eapol_authenticator *eapol = hapd->eapol_auth; 1797e28a4053SRui Paulo 1798e28a4053SRui Paulo if (hapd->conf->default_wep_key_len < 1) 1799e28a4053SRui Paulo return 0; 1800e28a4053SRui Paulo 1801e28a4053SRui Paulo os_free(eapol->default_wep_key); 1802e28a4053SRui Paulo eapol->default_wep_key = os_malloc(hapd->conf->default_wep_key_len); 1803e28a4053SRui Paulo if (eapol->default_wep_key == NULL || 1804f05cddf9SRui Paulo random_get_bytes(eapol->default_wep_key, 1805e28a4053SRui Paulo hapd->conf->default_wep_key_len)) { 18065b9c547cSRui Paulo wpa_printf(MSG_INFO, "Could not generate random WEP key"); 1807e28a4053SRui Paulo os_free(eapol->default_wep_key); 1808e28a4053SRui Paulo eapol->default_wep_key = NULL; 1809e28a4053SRui Paulo return -1; 1810e28a4053SRui Paulo } 1811e28a4053SRui Paulo 1812e28a4053SRui Paulo wpa_hexdump_key(MSG_DEBUG, "IEEE 802.1X: New default WEP key", 1813e28a4053SRui Paulo eapol->default_wep_key, 1814e28a4053SRui Paulo hapd->conf->default_wep_key_len); 1815e28a4053SRui Paulo 1816e28a4053SRui Paulo return 0; 1817e28a4053SRui Paulo } 1818e28a4053SRui Paulo 1819e28a4053SRui Paulo 1820e28a4053SRui Paulo static int ieee802_1x_sta_key_available(struct hostapd_data *hapd, 1821e28a4053SRui Paulo struct sta_info *sta, void *ctx) 1822e28a4053SRui Paulo { 1823e28a4053SRui Paulo if (sta->eapol_sm) { 1824e28a4053SRui Paulo sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; 1825e28a4053SRui Paulo eapol_auth_step(sta->eapol_sm); 1826e28a4053SRui Paulo } 1827e28a4053SRui Paulo return 0; 1828e28a4053SRui Paulo } 1829e28a4053SRui Paulo 1830e28a4053SRui Paulo 1831e28a4053SRui Paulo static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx) 1832e28a4053SRui Paulo { 1833e28a4053SRui Paulo struct hostapd_data *hapd = eloop_ctx; 1834e28a4053SRui Paulo struct eapol_authenticator *eapol = hapd->eapol_auth; 1835e28a4053SRui Paulo 1836e28a4053SRui Paulo if (eapol->default_wep_key_idx >= 3) 1837e28a4053SRui Paulo eapol->default_wep_key_idx = 1838e28a4053SRui Paulo hapd->conf->individual_wep_key_len > 0 ? 1 : 0; 1839e28a4053SRui Paulo else 1840e28a4053SRui Paulo eapol->default_wep_key_idx++; 1841e28a4053SRui Paulo 1842e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "IEEE 802.1X: New default WEP key index %d", 1843e28a4053SRui Paulo eapol->default_wep_key_idx); 1844e28a4053SRui Paulo 1845e28a4053SRui Paulo if (ieee802_1x_rekey_broadcast(hapd)) { 1846e28a4053SRui Paulo hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X, 1847e28a4053SRui Paulo HOSTAPD_LEVEL_WARNING, "failed to generate a " 1848e28a4053SRui Paulo "new broadcast key"); 1849e28a4053SRui Paulo os_free(eapol->default_wep_key); 1850e28a4053SRui Paulo eapol->default_wep_key = NULL; 1851e28a4053SRui Paulo return; 1852e28a4053SRui Paulo } 1853e28a4053SRui Paulo 1854e28a4053SRui Paulo /* TODO: Could setup key for RX here, but change default TX keyid only 1855e28a4053SRui Paulo * after new broadcast key has been sent to all stations. */ 1856f05cddf9SRui Paulo if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, 1857f05cddf9SRui Paulo broadcast_ether_addr, 1858e28a4053SRui Paulo eapol->default_wep_key_idx, 1, NULL, 0, 1859e28a4053SRui Paulo eapol->default_wep_key, 1860e28a4053SRui Paulo hapd->conf->default_wep_key_len)) { 1861e28a4053SRui Paulo hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X, 1862e28a4053SRui Paulo HOSTAPD_LEVEL_WARNING, "failed to configure a " 1863e28a4053SRui Paulo "new broadcast key"); 1864e28a4053SRui Paulo os_free(eapol->default_wep_key); 1865e28a4053SRui Paulo eapol->default_wep_key = NULL; 1866e28a4053SRui Paulo return; 1867e28a4053SRui Paulo } 1868e28a4053SRui Paulo 1869e28a4053SRui Paulo ap_for_each_sta(hapd, ieee802_1x_sta_key_available, NULL); 1870e28a4053SRui Paulo 1871e28a4053SRui Paulo if (hapd->conf->wep_rekeying_period > 0) { 1872e28a4053SRui Paulo eloop_register_timeout(hapd->conf->wep_rekeying_period, 0, 1873e28a4053SRui Paulo ieee802_1x_rekey, hapd, NULL); 1874e28a4053SRui Paulo } 1875e28a4053SRui Paulo } 1876e28a4053SRui Paulo 1877e28a4053SRui Paulo 1878e28a4053SRui Paulo static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type, 1879e28a4053SRui Paulo const u8 *data, size_t datalen) 1880e28a4053SRui Paulo { 1881e28a4053SRui Paulo #ifdef CONFIG_WPS 1882e28a4053SRui Paulo struct sta_info *sta = sta_ctx; 1883e28a4053SRui Paulo 1884e28a4053SRui Paulo if ((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) == 1885e28a4053SRui Paulo WLAN_STA_MAYBE_WPS) { 1886e28a4053SRui Paulo const u8 *identity; 1887e28a4053SRui Paulo size_t identity_len; 1888e28a4053SRui Paulo struct eapol_state_machine *sm = sta->eapol_sm; 1889e28a4053SRui Paulo 1890e28a4053SRui Paulo identity = eap_get_identity(sm->eap, &identity_len); 1891e28a4053SRui Paulo if (identity && 1892e28a4053SRui Paulo ((identity_len == WSC_ID_ENROLLEE_LEN && 1893e28a4053SRui Paulo os_memcmp(identity, WSC_ID_ENROLLEE, 1894e28a4053SRui Paulo WSC_ID_ENROLLEE_LEN) == 0) || 1895e28a4053SRui Paulo (identity_len == WSC_ID_REGISTRAR_LEN && 1896e28a4053SRui Paulo os_memcmp(identity, WSC_ID_REGISTRAR, 1897e28a4053SRui Paulo WSC_ID_REGISTRAR_LEN) == 0))) { 1898e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "WPS: WLAN_STA_MAYBE_WPS -> " 1899e28a4053SRui Paulo "WLAN_STA_WPS"); 1900e28a4053SRui Paulo sta->flags |= WLAN_STA_WPS; 1901e28a4053SRui Paulo } 1902e28a4053SRui Paulo } 1903e28a4053SRui Paulo #endif /* CONFIG_WPS */ 1904e28a4053SRui Paulo 1905e28a4053SRui Paulo ieee802_1x_send(ctx, sta_ctx, type, data, datalen); 1906e28a4053SRui Paulo } 1907e28a4053SRui Paulo 1908e28a4053SRui Paulo 1909e28a4053SRui Paulo static void ieee802_1x_aaa_send(void *ctx, void *sta_ctx, 1910e28a4053SRui Paulo const u8 *data, size_t datalen) 1911e28a4053SRui Paulo { 1912e28a4053SRui Paulo #ifndef CONFIG_NO_RADIUS 1913e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 1914e28a4053SRui Paulo struct sta_info *sta = sta_ctx; 1915e28a4053SRui Paulo 1916e28a4053SRui Paulo ieee802_1x_encapsulate_radius(hapd, sta, data, datalen); 1917e28a4053SRui Paulo #endif /* CONFIG_NO_RADIUS */ 1918e28a4053SRui Paulo } 1919e28a4053SRui Paulo 1920e28a4053SRui Paulo 1921e28a4053SRui Paulo static void _ieee802_1x_finished(void *ctx, void *sta_ctx, int success, 19225b9c547cSRui Paulo int preauth, int remediation) 1923e28a4053SRui Paulo { 1924e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 1925e28a4053SRui Paulo struct sta_info *sta = sta_ctx; 1926e28a4053SRui Paulo if (preauth) 1927e28a4053SRui Paulo rsn_preauth_finished(hapd, sta, success); 1928e28a4053SRui Paulo else 19295b9c547cSRui Paulo ieee802_1x_finished(hapd, sta, success, remediation); 1930e28a4053SRui Paulo } 1931e28a4053SRui Paulo 1932e28a4053SRui Paulo 1933e28a4053SRui Paulo static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity, 1934e28a4053SRui Paulo size_t identity_len, int phase2, 1935e28a4053SRui Paulo struct eap_user *user) 1936e28a4053SRui Paulo { 1937e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 1938e28a4053SRui Paulo const struct hostapd_eap_user *eap_user; 1939f05cddf9SRui Paulo int i; 1940*325151a3SRui Paulo int rv = -1; 1941e28a4053SRui Paulo 1942f05cddf9SRui Paulo eap_user = hostapd_get_eap_user(hapd, identity, identity_len, phase2); 1943e28a4053SRui Paulo if (eap_user == NULL) 1944*325151a3SRui Paulo goto out; 1945e28a4053SRui Paulo 1946e28a4053SRui Paulo os_memset(user, 0, sizeof(*user)); 1947e28a4053SRui Paulo user->phase2 = phase2; 1948f05cddf9SRui Paulo for (i = 0; i < EAP_MAX_METHODS; i++) { 1949e28a4053SRui Paulo user->methods[i].vendor = eap_user->methods[i].vendor; 1950e28a4053SRui Paulo user->methods[i].method = eap_user->methods[i].method; 1951e28a4053SRui Paulo } 1952e28a4053SRui Paulo 1953e28a4053SRui Paulo if (eap_user->password) { 1954e28a4053SRui Paulo user->password = os_malloc(eap_user->password_len); 1955e28a4053SRui Paulo if (user->password == NULL) 1956*325151a3SRui Paulo goto out; 1957e28a4053SRui Paulo os_memcpy(user->password, eap_user->password, 1958e28a4053SRui Paulo eap_user->password_len); 1959e28a4053SRui Paulo user->password_len = eap_user->password_len; 1960f05cddf9SRui Paulo user->password_hash = eap_user->password_hash; 1961e28a4053SRui Paulo } 1962e28a4053SRui Paulo user->force_version = eap_user->force_version; 19635b9c547cSRui Paulo user->macacl = eap_user->macacl; 1964e28a4053SRui Paulo user->ttls_auth = eap_user->ttls_auth; 19655b9c547cSRui Paulo user->remediation = eap_user->remediation; 1966*325151a3SRui Paulo rv = 0; 1967e28a4053SRui Paulo 1968*325151a3SRui Paulo out: 1969*325151a3SRui Paulo if (rv) 1970*325151a3SRui Paulo wpa_printf(MSG_DEBUG, "%s: Failed to find user", __func__); 1971*325151a3SRui Paulo 1972*325151a3SRui Paulo return rv; 1973e28a4053SRui Paulo } 1974e28a4053SRui Paulo 1975e28a4053SRui Paulo 1976e28a4053SRui Paulo static int ieee802_1x_sta_entry_alive(void *ctx, const u8 *addr) 1977e28a4053SRui Paulo { 1978e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 1979e28a4053SRui Paulo struct sta_info *sta; 1980e28a4053SRui Paulo sta = ap_get_sta(hapd, addr); 1981e28a4053SRui Paulo if (sta == NULL || sta->eapol_sm == NULL) 1982e28a4053SRui Paulo return 0; 1983e28a4053SRui Paulo return 1; 1984e28a4053SRui Paulo } 1985e28a4053SRui Paulo 1986e28a4053SRui Paulo 1987e28a4053SRui Paulo static void ieee802_1x_logger(void *ctx, const u8 *addr, 1988e28a4053SRui Paulo eapol_logger_level level, const char *txt) 1989e28a4053SRui Paulo { 1990e28a4053SRui Paulo #ifndef CONFIG_NO_HOSTAPD_LOGGER 1991e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 1992e28a4053SRui Paulo int hlevel; 1993e28a4053SRui Paulo 1994e28a4053SRui Paulo switch (level) { 1995e28a4053SRui Paulo case EAPOL_LOGGER_WARNING: 1996e28a4053SRui Paulo hlevel = HOSTAPD_LEVEL_WARNING; 1997e28a4053SRui Paulo break; 1998e28a4053SRui Paulo case EAPOL_LOGGER_INFO: 1999e28a4053SRui Paulo hlevel = HOSTAPD_LEVEL_INFO; 2000e28a4053SRui Paulo break; 2001e28a4053SRui Paulo case EAPOL_LOGGER_DEBUG: 2002e28a4053SRui Paulo default: 2003e28a4053SRui Paulo hlevel = HOSTAPD_LEVEL_DEBUG; 2004e28a4053SRui Paulo break; 2005e28a4053SRui Paulo } 2006e28a4053SRui Paulo 2007e28a4053SRui Paulo hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE8021X, hlevel, "%s", 2008e28a4053SRui Paulo txt); 2009e28a4053SRui Paulo #endif /* CONFIG_NO_HOSTAPD_LOGGER */ 2010e28a4053SRui Paulo } 2011e28a4053SRui Paulo 2012e28a4053SRui Paulo 2013e28a4053SRui Paulo static void ieee802_1x_set_port_authorized(void *ctx, void *sta_ctx, 2014e28a4053SRui Paulo int authorized) 2015e28a4053SRui Paulo { 2016e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 2017e28a4053SRui Paulo struct sta_info *sta = sta_ctx; 2018e28a4053SRui Paulo ieee802_1x_set_sta_authorized(hapd, sta, authorized); 2019e28a4053SRui Paulo } 2020e28a4053SRui Paulo 2021e28a4053SRui Paulo 2022e28a4053SRui Paulo static void _ieee802_1x_abort_auth(void *ctx, void *sta_ctx) 2023e28a4053SRui Paulo { 2024e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 2025e28a4053SRui Paulo struct sta_info *sta = sta_ctx; 2026e28a4053SRui Paulo ieee802_1x_abort_auth(hapd, sta); 2027e28a4053SRui Paulo } 2028e28a4053SRui Paulo 2029e28a4053SRui Paulo 2030e28a4053SRui Paulo static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx) 2031e28a4053SRui Paulo { 2032*325151a3SRui Paulo #ifndef CONFIG_FIPS 2033*325151a3SRui Paulo #ifndef CONFIG_NO_RC4 2034e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 2035e28a4053SRui Paulo struct sta_info *sta = sta_ctx; 2036e28a4053SRui Paulo ieee802_1x_tx_key(hapd, sta); 2037*325151a3SRui Paulo #endif /* CONFIG_NO_RC4 */ 2038*325151a3SRui Paulo #endif /* CONFIG_FIPS */ 2039e28a4053SRui Paulo } 2040e28a4053SRui Paulo 2041e28a4053SRui Paulo 2042e28a4053SRui Paulo static void ieee802_1x_eapol_event(void *ctx, void *sta_ctx, 2043e28a4053SRui Paulo enum eapol_event type) 2044e28a4053SRui Paulo { 2045e28a4053SRui Paulo /* struct hostapd_data *hapd = ctx; */ 2046e28a4053SRui Paulo struct sta_info *sta = sta_ctx; 2047e28a4053SRui Paulo switch (type) { 2048e28a4053SRui Paulo case EAPOL_AUTH_SM_CHANGE: 2049e28a4053SRui Paulo wpa_auth_sm_notify(sta->wpa_sm); 2050e28a4053SRui Paulo break; 2051e28a4053SRui Paulo case EAPOL_AUTH_REAUTHENTICATE: 2052e28a4053SRui Paulo wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL); 2053e28a4053SRui Paulo break; 2054e28a4053SRui Paulo } 2055e28a4053SRui Paulo } 2056e28a4053SRui Paulo 2057e28a4053SRui Paulo 20585b9c547cSRui Paulo #ifdef CONFIG_ERP 20595b9c547cSRui Paulo 20605b9c547cSRui Paulo static struct eap_server_erp_key * 20615b9c547cSRui Paulo ieee802_1x_erp_get_key(void *ctx, const char *keyname) 20625b9c547cSRui Paulo { 20635b9c547cSRui Paulo struct hostapd_data *hapd = ctx; 20645b9c547cSRui Paulo struct eap_server_erp_key *erp; 20655b9c547cSRui Paulo 20665b9c547cSRui Paulo dl_list_for_each(erp, &hapd->erp_keys, struct eap_server_erp_key, 20675b9c547cSRui Paulo list) { 20685b9c547cSRui Paulo if (os_strcmp(erp->keyname_nai, keyname) == 0) 20695b9c547cSRui Paulo return erp; 20705b9c547cSRui Paulo } 20715b9c547cSRui Paulo 20725b9c547cSRui Paulo return NULL; 20735b9c547cSRui Paulo } 20745b9c547cSRui Paulo 20755b9c547cSRui Paulo 20765b9c547cSRui Paulo static int ieee802_1x_erp_add_key(void *ctx, struct eap_server_erp_key *erp) 20775b9c547cSRui Paulo { 20785b9c547cSRui Paulo struct hostapd_data *hapd = ctx; 20795b9c547cSRui Paulo 20805b9c547cSRui Paulo dl_list_add(&hapd->erp_keys, &erp->list); 20815b9c547cSRui Paulo return 0; 20825b9c547cSRui Paulo } 20835b9c547cSRui Paulo 20845b9c547cSRui Paulo #endif /* CONFIG_ERP */ 20855b9c547cSRui Paulo 20865b9c547cSRui Paulo 2087e28a4053SRui Paulo int ieee802_1x_init(struct hostapd_data *hapd) 2088e28a4053SRui Paulo { 2089e28a4053SRui Paulo int i; 2090e28a4053SRui Paulo struct eapol_auth_config conf; 2091e28a4053SRui Paulo struct eapol_auth_cb cb; 2092e28a4053SRui Paulo 20935b9c547cSRui Paulo dl_list_init(&hapd->erp_keys); 20945b9c547cSRui Paulo 2095e28a4053SRui Paulo os_memset(&conf, 0, sizeof(conf)); 2096e28a4053SRui Paulo conf.ctx = hapd; 2097e28a4053SRui Paulo conf.eap_reauth_period = hapd->conf->eap_reauth_period; 2098e28a4053SRui Paulo conf.wpa = hapd->conf->wpa; 2099e28a4053SRui Paulo conf.individual_wep_key_len = hapd->conf->individual_wep_key_len; 2100e28a4053SRui Paulo conf.eap_server = hapd->conf->eap_server; 2101e28a4053SRui Paulo conf.ssl_ctx = hapd->ssl_ctx; 2102e28a4053SRui Paulo conf.msg_ctx = hapd->msg_ctx; 2103e28a4053SRui Paulo conf.eap_sim_db_priv = hapd->eap_sim_db_priv; 2104e28a4053SRui Paulo conf.eap_req_id_text = hapd->conf->eap_req_id_text; 2105e28a4053SRui Paulo conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len; 21065b9c547cSRui Paulo conf.erp_send_reauth_start = hapd->conf->erp_send_reauth_start; 21075b9c547cSRui Paulo conf.erp_domain = hapd->conf->erp_domain; 21085b9c547cSRui Paulo conf.erp = hapd->conf->eap_server_erp; 2109*325151a3SRui Paulo conf.tls_session_lifetime = hapd->conf->tls_session_lifetime; 2110e28a4053SRui Paulo conf.pac_opaque_encr_key = hapd->conf->pac_opaque_encr_key; 2111e28a4053SRui Paulo conf.eap_fast_a_id = hapd->conf->eap_fast_a_id; 2112e28a4053SRui Paulo conf.eap_fast_a_id_len = hapd->conf->eap_fast_a_id_len; 2113e28a4053SRui Paulo conf.eap_fast_a_id_info = hapd->conf->eap_fast_a_id_info; 2114e28a4053SRui Paulo conf.eap_fast_prov = hapd->conf->eap_fast_prov; 2115e28a4053SRui Paulo conf.pac_key_lifetime = hapd->conf->pac_key_lifetime; 2116e28a4053SRui Paulo conf.pac_key_refresh_time = hapd->conf->pac_key_refresh_time; 2117e28a4053SRui Paulo conf.eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind; 2118e28a4053SRui Paulo conf.tnc = hapd->conf->tnc; 2119e28a4053SRui Paulo conf.wps = hapd->wps; 2120f05cddf9SRui Paulo conf.fragment_size = hapd->conf->fragment_size; 2121f05cddf9SRui Paulo conf.pwd_group = hapd->conf->pwd_group; 2122f05cddf9SRui Paulo conf.pbc_in_m1 = hapd->conf->pbc_in_m1; 21235b9c547cSRui Paulo if (hapd->conf->server_id) { 21245b9c547cSRui Paulo conf.server_id = (const u8 *) hapd->conf->server_id; 21255b9c547cSRui Paulo conf.server_id_len = os_strlen(hapd->conf->server_id); 21265b9c547cSRui Paulo } else { 21275b9c547cSRui Paulo conf.server_id = (const u8 *) "hostapd"; 21285b9c547cSRui Paulo conf.server_id_len = 7; 21295b9c547cSRui Paulo } 2130e28a4053SRui Paulo 2131e28a4053SRui Paulo os_memset(&cb, 0, sizeof(cb)); 2132e28a4053SRui Paulo cb.eapol_send = ieee802_1x_eapol_send; 2133e28a4053SRui Paulo cb.aaa_send = ieee802_1x_aaa_send; 2134e28a4053SRui Paulo cb.finished = _ieee802_1x_finished; 2135e28a4053SRui Paulo cb.get_eap_user = ieee802_1x_get_eap_user; 2136e28a4053SRui Paulo cb.sta_entry_alive = ieee802_1x_sta_entry_alive; 2137e28a4053SRui Paulo cb.logger = ieee802_1x_logger; 2138e28a4053SRui Paulo cb.set_port_authorized = ieee802_1x_set_port_authorized; 2139e28a4053SRui Paulo cb.abort_auth = _ieee802_1x_abort_auth; 2140e28a4053SRui Paulo cb.tx_key = _ieee802_1x_tx_key; 2141e28a4053SRui Paulo cb.eapol_event = ieee802_1x_eapol_event; 21425b9c547cSRui Paulo #ifdef CONFIG_ERP 21435b9c547cSRui Paulo cb.erp_get_key = ieee802_1x_erp_get_key; 21445b9c547cSRui Paulo cb.erp_add_key = ieee802_1x_erp_add_key; 21455b9c547cSRui Paulo #endif /* CONFIG_ERP */ 2146e28a4053SRui Paulo 2147e28a4053SRui Paulo hapd->eapol_auth = eapol_auth_init(&conf, &cb); 2148e28a4053SRui Paulo if (hapd->eapol_auth == NULL) 2149e28a4053SRui Paulo return -1; 2150e28a4053SRui Paulo 2151e28a4053SRui Paulo if ((hapd->conf->ieee802_1x || hapd->conf->wpa) && 2152f05cddf9SRui Paulo hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1)) 2153e28a4053SRui Paulo return -1; 2154e28a4053SRui Paulo 2155e28a4053SRui Paulo #ifndef CONFIG_NO_RADIUS 2156e28a4053SRui Paulo if (radius_client_register(hapd->radius, RADIUS_AUTH, 2157e28a4053SRui Paulo ieee802_1x_receive_auth, hapd)) 2158e28a4053SRui Paulo return -1; 2159e28a4053SRui Paulo #endif /* CONFIG_NO_RADIUS */ 2160e28a4053SRui Paulo 2161e28a4053SRui Paulo if (hapd->conf->default_wep_key_len) { 2162e28a4053SRui Paulo for (i = 0; i < 4; i++) 2163f05cddf9SRui Paulo hostapd_drv_set_key(hapd->conf->iface, hapd, 2164e28a4053SRui Paulo WPA_ALG_NONE, NULL, i, 0, NULL, 0, 2165e28a4053SRui Paulo NULL, 0); 2166e28a4053SRui Paulo 2167e28a4053SRui Paulo ieee802_1x_rekey(hapd, NULL); 2168e28a4053SRui Paulo 2169e28a4053SRui Paulo if (hapd->eapol_auth->default_wep_key == NULL) 2170e28a4053SRui Paulo return -1; 2171e28a4053SRui Paulo } 2172e28a4053SRui Paulo 2173e28a4053SRui Paulo return 0; 2174e28a4053SRui Paulo } 2175e28a4053SRui Paulo 2176e28a4053SRui Paulo 21775b9c547cSRui Paulo void ieee802_1x_erp_flush(struct hostapd_data *hapd) 21785b9c547cSRui Paulo { 21795b9c547cSRui Paulo struct eap_server_erp_key *erp; 21805b9c547cSRui Paulo 21815b9c547cSRui Paulo while ((erp = dl_list_first(&hapd->erp_keys, struct eap_server_erp_key, 21825b9c547cSRui Paulo list)) != NULL) { 21835b9c547cSRui Paulo dl_list_del(&erp->list); 21845b9c547cSRui Paulo bin_clear_free(erp, sizeof(*erp)); 21855b9c547cSRui Paulo } 21865b9c547cSRui Paulo } 21875b9c547cSRui Paulo 21885b9c547cSRui Paulo 2189e28a4053SRui Paulo void ieee802_1x_deinit(struct hostapd_data *hapd) 2190e28a4053SRui Paulo { 2191e28a4053SRui Paulo eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL); 2192e28a4053SRui Paulo 2193e28a4053SRui Paulo if (hapd->driver != NULL && 2194e28a4053SRui Paulo (hapd->conf->ieee802_1x || hapd->conf->wpa)) 2195f05cddf9SRui Paulo hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0); 2196e28a4053SRui Paulo 2197e28a4053SRui Paulo eapol_auth_deinit(hapd->eapol_auth); 2198e28a4053SRui Paulo hapd->eapol_auth = NULL; 21995b9c547cSRui Paulo 22005b9c547cSRui Paulo ieee802_1x_erp_flush(hapd); 2201e28a4053SRui Paulo } 2202e28a4053SRui Paulo 2203e28a4053SRui Paulo 2204e28a4053SRui Paulo int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, 2205e28a4053SRui Paulo const u8 *buf, size_t len, int ack) 2206e28a4053SRui Paulo { 2207e28a4053SRui Paulo struct ieee80211_hdr *hdr; 2208e28a4053SRui Paulo u8 *pos; 2209e28a4053SRui Paulo const unsigned char rfc1042_hdr[ETH_ALEN] = 2210e28a4053SRui Paulo { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; 2211e28a4053SRui Paulo 2212e28a4053SRui Paulo if (sta == NULL) 2213e28a4053SRui Paulo return -1; 2214f05cddf9SRui Paulo if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2) 2215e28a4053SRui Paulo return 0; 2216e28a4053SRui Paulo 2217e28a4053SRui Paulo hdr = (struct ieee80211_hdr *) buf; 2218e28a4053SRui Paulo pos = (u8 *) (hdr + 1); 2219e28a4053SRui Paulo if (os_memcmp(pos, rfc1042_hdr, sizeof(rfc1042_hdr)) != 0) 2220e28a4053SRui Paulo return 0; 2221e28a4053SRui Paulo pos += sizeof(rfc1042_hdr); 2222e28a4053SRui Paulo if (WPA_GET_BE16(pos) != ETH_P_PAE) 2223e28a4053SRui Paulo return 0; 2224e28a4053SRui Paulo pos += 2; 2225e28a4053SRui Paulo 2226f05cddf9SRui Paulo return ieee802_1x_eapol_tx_status(hapd, sta, pos, buf + len - pos, 2227f05cddf9SRui Paulo ack); 2228f05cddf9SRui Paulo } 2229e28a4053SRui Paulo 2230f05cddf9SRui Paulo 2231f05cddf9SRui Paulo int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta, 2232f05cddf9SRui Paulo const u8 *buf, int len, int ack) 2233f05cddf9SRui Paulo { 2234f05cddf9SRui Paulo const struct ieee802_1x_hdr *xhdr = 2235f05cddf9SRui Paulo (const struct ieee802_1x_hdr *) buf; 2236f05cddf9SRui Paulo const u8 *pos = buf + sizeof(*xhdr); 2237f05cddf9SRui Paulo struct ieee802_1x_eapol_key *key; 2238f05cddf9SRui Paulo 2239f05cddf9SRui Paulo if (len < (int) sizeof(*xhdr)) 2240f05cddf9SRui Paulo return 0; 2241e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d " 2242e28a4053SRui Paulo "type=%d length=%d - ack=%d", 2243e28a4053SRui Paulo MAC2STR(sta->addr), xhdr->version, xhdr->type, 2244e28a4053SRui Paulo be_to_host16(xhdr->length), ack); 2245e28a4053SRui Paulo 2246f05cddf9SRui Paulo if (xhdr->type != IEEE802_1X_TYPE_EAPOL_KEY) 2247f05cddf9SRui Paulo return 0; 2248f05cddf9SRui Paulo 2249f05cddf9SRui Paulo if (pos + sizeof(struct wpa_eapol_key) <= buf + len) { 2250f05cddf9SRui Paulo const struct wpa_eapol_key *wpa; 2251f05cddf9SRui Paulo wpa = (const struct wpa_eapol_key *) pos; 2252f05cddf9SRui Paulo if (wpa->type == EAPOL_KEY_TYPE_RSN || 2253f05cddf9SRui Paulo wpa->type == EAPOL_KEY_TYPE_WPA) 2254f05cddf9SRui Paulo wpa_auth_eapol_key_tx_status(hapd->wpa_auth, 2255f05cddf9SRui Paulo sta->wpa_sm, ack); 2256f05cddf9SRui Paulo } 2257f05cddf9SRui Paulo 2258e28a4053SRui Paulo /* EAPOL EAP-Packet packets are eventually re-sent by either Supplicant 2259e28a4053SRui Paulo * or Authenticator state machines, but EAPOL-Key packets are not 2260f05cddf9SRui Paulo * retransmitted in case of failure. Try to re-send failed EAPOL-Key 2261e28a4053SRui Paulo * packets couple of times because otherwise STA keys become 2262e28a4053SRui Paulo * unsynchronized with AP. */ 2263f05cddf9SRui Paulo if (!ack && pos + sizeof(*key) <= buf + len) { 2264e28a4053SRui Paulo key = (struct ieee802_1x_eapol_key *) pos; 2265e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 2266e28a4053SRui Paulo HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key " 2267e28a4053SRui Paulo "frame (%scast index=%d)", 2268e28a4053SRui Paulo key->key_index & BIT(7) ? "uni" : "broad", 2269e28a4053SRui Paulo key->key_index & ~BIT(7)); 2270e28a4053SRui Paulo /* TODO: re-send EAPOL-Key couple of times (with short delay 2271e28a4053SRui Paulo * between them?). If all attempt fail, report error and 2272e28a4053SRui Paulo * deauthenticate STA so that it will get new keys when 2273e28a4053SRui Paulo * authenticating again (e.g., after returning in range). 2274e28a4053SRui Paulo * Separate limit/transmit state needed both for unicast and 2275e28a4053SRui Paulo * broadcast keys(?) */ 2276e28a4053SRui Paulo } 2277e28a4053SRui Paulo /* TODO: could move unicast key configuration from ieee802_1x_tx_key() 2278e28a4053SRui Paulo * to here and change the key only if the EAPOL-Key packet was Acked. 2279e28a4053SRui Paulo */ 2280e28a4053SRui Paulo 2281e28a4053SRui Paulo return 1; 2282e28a4053SRui Paulo } 2283e28a4053SRui Paulo 2284e28a4053SRui Paulo 2285e28a4053SRui Paulo u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len) 2286e28a4053SRui Paulo { 2287e28a4053SRui Paulo if (sm == NULL || sm->identity == NULL) 2288e28a4053SRui Paulo return NULL; 2289e28a4053SRui Paulo 2290e28a4053SRui Paulo *len = sm->identity_len; 2291e28a4053SRui Paulo return sm->identity; 2292e28a4053SRui Paulo } 2293e28a4053SRui Paulo 2294e28a4053SRui Paulo 2295e28a4053SRui Paulo u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len, 2296e28a4053SRui Paulo int idx) 2297e28a4053SRui Paulo { 2298e28a4053SRui Paulo if (sm == NULL || sm->radius_class.attr == NULL || 2299e28a4053SRui Paulo idx >= (int) sm->radius_class.count) 2300e28a4053SRui Paulo return NULL; 2301e28a4053SRui Paulo 2302e28a4053SRui Paulo *len = sm->radius_class.attr[idx].len; 2303e28a4053SRui Paulo return sm->radius_class.attr[idx].data; 2304e28a4053SRui Paulo } 2305e28a4053SRui Paulo 2306e28a4053SRui Paulo 2307f05cddf9SRui Paulo struct wpabuf * ieee802_1x_get_radius_cui(struct eapol_state_machine *sm) 2308f05cddf9SRui Paulo { 2309f05cddf9SRui Paulo if (sm == NULL) 2310f05cddf9SRui Paulo return NULL; 2311f05cddf9SRui Paulo return sm->radius_cui; 2312f05cddf9SRui Paulo } 2313f05cddf9SRui Paulo 2314f05cddf9SRui Paulo 2315e28a4053SRui Paulo const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len) 2316e28a4053SRui Paulo { 2317f05cddf9SRui Paulo *len = 0; 2318e28a4053SRui Paulo if (sm == NULL) 2319e28a4053SRui Paulo return NULL; 2320e28a4053SRui Paulo 2321e28a4053SRui Paulo *len = sm->eap_if->eapKeyDataLen; 2322e28a4053SRui Paulo return sm->eap_if->eapKeyData; 2323e28a4053SRui Paulo } 2324e28a4053SRui Paulo 2325e28a4053SRui Paulo 2326e28a4053SRui Paulo void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, 2327e28a4053SRui Paulo int enabled) 2328e28a4053SRui Paulo { 2329e28a4053SRui Paulo if (sm == NULL) 2330e28a4053SRui Paulo return; 2331e28a4053SRui Paulo sm->eap_if->portEnabled = enabled ? TRUE : FALSE; 2332e28a4053SRui Paulo eapol_auth_step(sm); 2333e28a4053SRui Paulo } 2334e28a4053SRui Paulo 2335e28a4053SRui Paulo 2336e28a4053SRui Paulo void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, 2337e28a4053SRui Paulo int valid) 2338e28a4053SRui Paulo { 2339e28a4053SRui Paulo if (sm == NULL) 2340e28a4053SRui Paulo return; 2341e28a4053SRui Paulo sm->portValid = valid ? TRUE : FALSE; 2342e28a4053SRui Paulo eapol_auth_step(sm); 2343e28a4053SRui Paulo } 2344e28a4053SRui Paulo 2345e28a4053SRui Paulo 2346e28a4053SRui Paulo void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth) 2347e28a4053SRui Paulo { 2348e28a4053SRui Paulo if (sm == NULL) 2349e28a4053SRui Paulo return; 2350e28a4053SRui Paulo if (pre_auth) 2351e28a4053SRui Paulo sm->flags |= EAPOL_SM_PREAUTH; 2352e28a4053SRui Paulo else 2353e28a4053SRui Paulo sm->flags &= ~EAPOL_SM_PREAUTH; 2354e28a4053SRui Paulo } 2355e28a4053SRui Paulo 2356e28a4053SRui Paulo 2357*325151a3SRui Paulo static const char * bool_txt(Boolean val) 2358e28a4053SRui Paulo { 2359*325151a3SRui Paulo return val ? "TRUE" : "FALSE"; 2360e28a4053SRui Paulo } 2361e28a4053SRui Paulo 2362e28a4053SRui Paulo 2363e28a4053SRui Paulo int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen) 2364e28a4053SRui Paulo { 2365e28a4053SRui Paulo /* TODO */ 2366e28a4053SRui Paulo return 0; 2367e28a4053SRui Paulo } 2368e28a4053SRui Paulo 2369e28a4053SRui Paulo 2370e28a4053SRui Paulo int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, 2371e28a4053SRui Paulo char *buf, size_t buflen) 2372e28a4053SRui Paulo { 2373e28a4053SRui Paulo int len = 0, ret; 2374e28a4053SRui Paulo struct eapol_state_machine *sm = sta->eapol_sm; 23755b9c547cSRui Paulo struct os_reltime diff; 23765b9c547cSRui Paulo const char *name1; 23775b9c547cSRui Paulo const char *name2; 2378e28a4053SRui Paulo 2379e28a4053SRui Paulo if (sm == NULL) 2380e28a4053SRui Paulo return 0; 2381e28a4053SRui Paulo 2382e28a4053SRui Paulo ret = os_snprintf(buf + len, buflen - len, 2383e28a4053SRui Paulo "dot1xPaePortNumber=%d\n" 2384e28a4053SRui Paulo "dot1xPaePortProtocolVersion=%d\n" 2385e28a4053SRui Paulo "dot1xPaePortCapabilities=1\n" 2386e28a4053SRui Paulo "dot1xPaePortInitialize=%d\n" 2387e28a4053SRui Paulo "dot1xPaePortReauthenticate=FALSE\n", 2388e28a4053SRui Paulo sta->aid, 2389e28a4053SRui Paulo EAPOL_VERSION, 2390e28a4053SRui Paulo sm->initialize); 23915b9c547cSRui Paulo if (os_snprintf_error(buflen - len, ret)) 2392e28a4053SRui Paulo return len; 2393e28a4053SRui Paulo len += ret; 2394e28a4053SRui Paulo 2395e28a4053SRui Paulo /* dot1xAuthConfigTable */ 2396e28a4053SRui Paulo ret = os_snprintf(buf + len, buflen - len, 2397e28a4053SRui Paulo "dot1xAuthPaeState=%d\n" 2398e28a4053SRui Paulo "dot1xAuthBackendAuthState=%d\n" 2399e28a4053SRui Paulo "dot1xAuthAdminControlledDirections=%d\n" 2400e28a4053SRui Paulo "dot1xAuthOperControlledDirections=%d\n" 2401e28a4053SRui Paulo "dot1xAuthAuthControlledPortStatus=%d\n" 2402e28a4053SRui Paulo "dot1xAuthAuthControlledPortControl=%d\n" 2403e28a4053SRui Paulo "dot1xAuthQuietPeriod=%u\n" 2404e28a4053SRui Paulo "dot1xAuthServerTimeout=%u\n" 2405e28a4053SRui Paulo "dot1xAuthReAuthPeriod=%u\n" 2406e28a4053SRui Paulo "dot1xAuthReAuthEnabled=%s\n" 2407e28a4053SRui Paulo "dot1xAuthKeyTxEnabled=%s\n", 2408e28a4053SRui Paulo sm->auth_pae_state + 1, 2409e28a4053SRui Paulo sm->be_auth_state + 1, 2410e28a4053SRui Paulo sm->adminControlledDirections, 2411e28a4053SRui Paulo sm->operControlledDirections, 2412e28a4053SRui Paulo sm->authPortStatus, 2413e28a4053SRui Paulo sm->portControl, 2414e28a4053SRui Paulo sm->quietPeriod, 2415e28a4053SRui Paulo sm->serverTimeout, 2416e28a4053SRui Paulo sm->reAuthPeriod, 2417e28a4053SRui Paulo bool_txt(sm->reAuthEnabled), 2418e28a4053SRui Paulo bool_txt(sm->keyTxEnabled)); 24195b9c547cSRui Paulo if (os_snprintf_error(buflen - len, ret)) 2420e28a4053SRui Paulo return len; 2421e28a4053SRui Paulo len += ret; 2422e28a4053SRui Paulo 2423e28a4053SRui Paulo /* dot1xAuthStatsTable */ 2424e28a4053SRui Paulo ret = os_snprintf(buf + len, buflen - len, 2425e28a4053SRui Paulo "dot1xAuthEapolFramesRx=%u\n" 2426e28a4053SRui Paulo "dot1xAuthEapolFramesTx=%u\n" 2427e28a4053SRui Paulo "dot1xAuthEapolStartFramesRx=%u\n" 2428e28a4053SRui Paulo "dot1xAuthEapolLogoffFramesRx=%u\n" 2429e28a4053SRui Paulo "dot1xAuthEapolRespIdFramesRx=%u\n" 2430e28a4053SRui Paulo "dot1xAuthEapolRespFramesRx=%u\n" 2431e28a4053SRui Paulo "dot1xAuthEapolReqIdFramesTx=%u\n" 2432e28a4053SRui Paulo "dot1xAuthEapolReqFramesTx=%u\n" 2433e28a4053SRui Paulo "dot1xAuthInvalidEapolFramesRx=%u\n" 2434e28a4053SRui Paulo "dot1xAuthEapLengthErrorFramesRx=%u\n" 2435e28a4053SRui Paulo "dot1xAuthLastEapolFrameVersion=%u\n" 2436e28a4053SRui Paulo "dot1xAuthLastEapolFrameSource=" MACSTR "\n", 2437e28a4053SRui Paulo sm->dot1xAuthEapolFramesRx, 2438e28a4053SRui Paulo sm->dot1xAuthEapolFramesTx, 2439e28a4053SRui Paulo sm->dot1xAuthEapolStartFramesRx, 2440e28a4053SRui Paulo sm->dot1xAuthEapolLogoffFramesRx, 2441e28a4053SRui Paulo sm->dot1xAuthEapolRespIdFramesRx, 2442e28a4053SRui Paulo sm->dot1xAuthEapolRespFramesRx, 2443e28a4053SRui Paulo sm->dot1xAuthEapolReqIdFramesTx, 2444e28a4053SRui Paulo sm->dot1xAuthEapolReqFramesTx, 2445e28a4053SRui Paulo sm->dot1xAuthInvalidEapolFramesRx, 2446e28a4053SRui Paulo sm->dot1xAuthEapLengthErrorFramesRx, 2447e28a4053SRui Paulo sm->dot1xAuthLastEapolFrameVersion, 2448e28a4053SRui Paulo MAC2STR(sm->addr)); 24495b9c547cSRui Paulo if (os_snprintf_error(buflen - len, ret)) 2450e28a4053SRui Paulo return len; 2451e28a4053SRui Paulo len += ret; 2452e28a4053SRui Paulo 2453e28a4053SRui Paulo /* dot1xAuthDiagTable */ 2454e28a4053SRui Paulo ret = os_snprintf(buf + len, buflen - len, 2455e28a4053SRui Paulo "dot1xAuthEntersConnecting=%u\n" 2456e28a4053SRui Paulo "dot1xAuthEapLogoffsWhileConnecting=%u\n" 2457e28a4053SRui Paulo "dot1xAuthEntersAuthenticating=%u\n" 2458e28a4053SRui Paulo "dot1xAuthAuthSuccessesWhileAuthenticating=%u\n" 2459e28a4053SRui Paulo "dot1xAuthAuthTimeoutsWhileAuthenticating=%u\n" 2460e28a4053SRui Paulo "dot1xAuthAuthFailWhileAuthenticating=%u\n" 2461e28a4053SRui Paulo "dot1xAuthAuthEapStartsWhileAuthenticating=%u\n" 2462e28a4053SRui Paulo "dot1xAuthAuthEapLogoffWhileAuthenticating=%u\n" 2463e28a4053SRui Paulo "dot1xAuthAuthReauthsWhileAuthenticated=%u\n" 2464e28a4053SRui Paulo "dot1xAuthAuthEapStartsWhileAuthenticated=%u\n" 2465e28a4053SRui Paulo "dot1xAuthAuthEapLogoffWhileAuthenticated=%u\n" 2466e28a4053SRui Paulo "dot1xAuthBackendResponses=%u\n" 2467e28a4053SRui Paulo "dot1xAuthBackendAccessChallenges=%u\n" 2468e28a4053SRui Paulo "dot1xAuthBackendOtherRequestsToSupplicant=%u\n" 2469e28a4053SRui Paulo "dot1xAuthBackendAuthSuccesses=%u\n" 2470e28a4053SRui Paulo "dot1xAuthBackendAuthFails=%u\n", 2471e28a4053SRui Paulo sm->authEntersConnecting, 2472e28a4053SRui Paulo sm->authEapLogoffsWhileConnecting, 2473e28a4053SRui Paulo sm->authEntersAuthenticating, 2474e28a4053SRui Paulo sm->authAuthSuccessesWhileAuthenticating, 2475e28a4053SRui Paulo sm->authAuthTimeoutsWhileAuthenticating, 2476e28a4053SRui Paulo sm->authAuthFailWhileAuthenticating, 2477e28a4053SRui Paulo sm->authAuthEapStartsWhileAuthenticating, 2478e28a4053SRui Paulo sm->authAuthEapLogoffWhileAuthenticating, 2479e28a4053SRui Paulo sm->authAuthReauthsWhileAuthenticated, 2480e28a4053SRui Paulo sm->authAuthEapStartsWhileAuthenticated, 2481e28a4053SRui Paulo sm->authAuthEapLogoffWhileAuthenticated, 2482e28a4053SRui Paulo sm->backendResponses, 2483e28a4053SRui Paulo sm->backendAccessChallenges, 2484e28a4053SRui Paulo sm->backendOtherRequestsToSupplicant, 2485e28a4053SRui Paulo sm->backendAuthSuccesses, 2486e28a4053SRui Paulo sm->backendAuthFails); 24875b9c547cSRui Paulo if (os_snprintf_error(buflen - len, ret)) 2488e28a4053SRui Paulo return len; 2489e28a4053SRui Paulo len += ret; 2490e28a4053SRui Paulo 2491e28a4053SRui Paulo /* dot1xAuthSessionStatsTable */ 24925b9c547cSRui Paulo os_reltime_age(&sta->acct_session_start, &diff); 2493e28a4053SRui Paulo ret = os_snprintf(buf + len, buflen - len, 2494e28a4053SRui Paulo /* TODO: dot1xAuthSessionOctetsRx */ 2495e28a4053SRui Paulo /* TODO: dot1xAuthSessionOctetsTx */ 2496e28a4053SRui Paulo /* TODO: dot1xAuthSessionFramesRx */ 2497e28a4053SRui Paulo /* TODO: dot1xAuthSessionFramesTx */ 2498e28a4053SRui Paulo "dot1xAuthSessionId=%08X-%08X\n" 2499e28a4053SRui Paulo "dot1xAuthSessionAuthenticMethod=%d\n" 2500e28a4053SRui Paulo "dot1xAuthSessionTime=%u\n" 2501e28a4053SRui Paulo "dot1xAuthSessionTerminateCause=999\n" 2502e28a4053SRui Paulo "dot1xAuthSessionUserName=%s\n", 2503e28a4053SRui Paulo sta->acct_session_id_hi, sta->acct_session_id_lo, 2504e28a4053SRui Paulo (wpa_key_mgmt_wpa_ieee8021x( 2505e28a4053SRui Paulo wpa_auth_sta_key_mgmt(sta->wpa_sm))) ? 2506e28a4053SRui Paulo 1 : 2, 25075b9c547cSRui Paulo (unsigned int) diff.sec, 2508e28a4053SRui Paulo sm->identity); 25095b9c547cSRui Paulo if (os_snprintf_error(buflen - len, ret)) 25105b9c547cSRui Paulo return len; 25115b9c547cSRui Paulo len += ret; 25125b9c547cSRui Paulo 25135b9c547cSRui Paulo if (sm->acct_multi_session_id_hi) { 25145b9c547cSRui Paulo ret = os_snprintf(buf + len, buflen - len, 25155b9c547cSRui Paulo "authMultiSessionId=%08X+%08X\n", 25165b9c547cSRui Paulo sm->acct_multi_session_id_hi, 25175b9c547cSRui Paulo sm->acct_multi_session_id_lo); 25185b9c547cSRui Paulo if (os_snprintf_error(buflen - len, ret)) 25195b9c547cSRui Paulo return len; 25205b9c547cSRui Paulo len += ret; 25215b9c547cSRui Paulo } 25225b9c547cSRui Paulo 25235b9c547cSRui Paulo name1 = eap_server_get_name(0, sm->eap_type_authsrv); 25245b9c547cSRui Paulo name2 = eap_server_get_name(0, sm->eap_type_supp); 25255b9c547cSRui Paulo ret = os_snprintf(buf + len, buflen - len, 25265b9c547cSRui Paulo "last_eap_type_as=%d (%s)\n" 25275b9c547cSRui Paulo "last_eap_type_sta=%d (%s)\n", 25285b9c547cSRui Paulo sm->eap_type_authsrv, name1, 25295b9c547cSRui Paulo sm->eap_type_supp, name2); 25305b9c547cSRui Paulo if (os_snprintf_error(buflen - len, ret)) 2531e28a4053SRui Paulo return len; 2532e28a4053SRui Paulo len += ret; 2533e28a4053SRui Paulo 2534e28a4053SRui Paulo return len; 2535e28a4053SRui Paulo } 2536e28a4053SRui Paulo 2537e28a4053SRui Paulo 2538e28a4053SRui Paulo static void ieee802_1x_finished(struct hostapd_data *hapd, 25395b9c547cSRui Paulo struct sta_info *sta, int success, 25405b9c547cSRui Paulo int remediation) 2541e28a4053SRui Paulo { 2542e28a4053SRui Paulo const u8 *key; 2543e28a4053SRui Paulo size_t len; 2544e28a4053SRui Paulo /* TODO: get PMKLifetime from WPA parameters */ 2545e28a4053SRui Paulo static const int dot11RSNAConfigPMKLifetime = 43200; 25465b9c547cSRui Paulo unsigned int session_timeout; 25475b9c547cSRui Paulo 25485b9c547cSRui Paulo #ifdef CONFIG_HS20 25495b9c547cSRui Paulo if (remediation && !sta->remediation) { 25505b9c547cSRui Paulo sta->remediation = 1; 25515b9c547cSRui Paulo os_free(sta->remediation_url); 25525b9c547cSRui Paulo sta->remediation_url = 25535b9c547cSRui Paulo os_strdup(hapd->conf->subscr_remediation_url); 25545b9c547cSRui Paulo sta->remediation_method = 1; /* SOAP-XML SPP */ 25555b9c547cSRui Paulo } 25565b9c547cSRui Paulo 25575b9c547cSRui Paulo if (success) { 25585b9c547cSRui Paulo if (sta->remediation) { 25595b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification " 25605b9c547cSRui Paulo "to " MACSTR " to indicate Subscription " 25615b9c547cSRui Paulo "Remediation", 25625b9c547cSRui Paulo MAC2STR(sta->addr)); 25635b9c547cSRui Paulo hs20_send_wnm_notification(hapd, sta->addr, 25645b9c547cSRui Paulo sta->remediation_method, 25655b9c547cSRui Paulo sta->remediation_url); 25665b9c547cSRui Paulo os_free(sta->remediation_url); 25675b9c547cSRui Paulo sta->remediation_url = NULL; 25685b9c547cSRui Paulo } 25695b9c547cSRui Paulo 25705b9c547cSRui Paulo if (sta->hs20_deauth_req) { 25715b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification " 25725b9c547cSRui Paulo "to " MACSTR " to indicate imminent " 25735b9c547cSRui Paulo "deauthentication", MAC2STR(sta->addr)); 25745b9c547cSRui Paulo hs20_send_wnm_notification_deauth_req( 25755b9c547cSRui Paulo hapd, sta->addr, sta->hs20_deauth_req); 25765b9c547cSRui Paulo } 25775b9c547cSRui Paulo } 25785b9c547cSRui Paulo #endif /* CONFIG_HS20 */ 2579e28a4053SRui Paulo 2580e28a4053SRui Paulo key = ieee802_1x_get_key(sta->eapol_sm, &len); 25815b9c547cSRui Paulo if (sta->session_timeout_set) 25825b9c547cSRui Paulo session_timeout = sta->session_timeout; 25835b9c547cSRui Paulo else 25845b9c547cSRui Paulo session_timeout = dot11RSNAConfigPMKLifetime; 25855b9c547cSRui Paulo if (success && key && len >= PMK_LEN && !sta->remediation && 25865b9c547cSRui Paulo !sta->hs20_deauth_requested && 25875b9c547cSRui Paulo wpa_auth_pmksa_add(sta->wpa_sm, key, session_timeout, 2588e28a4053SRui Paulo sta->eapol_sm) == 0) { 2589e28a4053SRui Paulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, 2590e28a4053SRui Paulo HOSTAPD_LEVEL_DEBUG, 2591e28a4053SRui Paulo "Added PMKSA cache entry (IEEE 802.1X)"); 2592e28a4053SRui Paulo } 2593e28a4053SRui Paulo 2594f05cddf9SRui Paulo if (!success) { 2595e28a4053SRui Paulo /* 2596e28a4053SRui Paulo * Many devices require deauthentication after WPS provisioning 2597e28a4053SRui Paulo * and some may not be be able to do that themselves, so 2598f05cddf9SRui Paulo * disconnect the client here. In addition, this may also 2599f05cddf9SRui Paulo * benefit IEEE 802.1X/EAPOL authentication cases, too since 2600f05cddf9SRui Paulo * the EAPOL PAE state machine would remain in HELD state for 2601f05cddf9SRui Paulo * considerable amount of time and some EAP methods, like 2602f05cddf9SRui Paulo * EAP-FAST with anonymous provisioning, may require another 2603f05cddf9SRui Paulo * EAPOL authentication to be started to complete connection. 2604e28a4053SRui Paulo */ 2605f05cddf9SRui Paulo wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "IEEE 802.1X: Force " 2606f05cddf9SRui Paulo "disconnection after EAP-Failure"); 2607e28a4053SRui Paulo /* Add a small sleep to increase likelihood of previously 2608e28a4053SRui Paulo * requested EAP-Failure TX getting out before this should the 2609e28a4053SRui Paulo * driver reorder operations. 2610e28a4053SRui Paulo */ 2611e28a4053SRui Paulo os_sleep(0, 10000); 2612e28a4053SRui Paulo ap_sta_disconnect(hapd, sta, sta->addr, 2613f05cddf9SRui Paulo WLAN_REASON_IEEE_802_1X_AUTH_FAILED); 26145b9c547cSRui Paulo hostapd_wps_eap_completed(hapd); 2615e28a4053SRui Paulo } 2616e28a4053SRui Paulo } 2617