18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / IEEE 802.1X-2004 Authenticator 3c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/md5.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius/radius.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius/radius_client.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_wsc_common.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_auth/eapol_auth_sm.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_auth/eapol_auth_sm_i.h" 231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "p2p/p2p.h" 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "hostapd.h" 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "accounting.h" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "sta_info.h" 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth.h" 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "preauth_auth.h" 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "pmksa_cache_auth.h" 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_config.h" 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_drv_ops.h" 32fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#include "wps_hostapd.h" 33f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#include "hs20.h" 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_1x.h" 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_finished(struct hostapd_data *hapd, 38f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct sta_info *sta, int success, 39f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int remediation); 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta, 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 type, const u8 *data, size_t datalen) 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *xhdr; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int encrypt = 0; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = sizeof(*xhdr) + datalen; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(len); 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "malloc() failed for " 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ieee802_1x_send(len=%lu)", 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len); 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xhdr = (struct ieee802_1x_hdr *) buf; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xhdr->version = hapd->conf->eapol_version; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xhdr->type = type; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xhdr->length = host_to_be16(datalen); 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (datalen > 0 && data != NULL) 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(xhdr + 1, data, datalen); 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_pairwise_set(sta->wpa_sm)) 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encrypt = 1; 696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS 706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (hapd->ext_eapol_frame_io) { 716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t hex_len = 2 * len + 1; 726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt char *hex = os_malloc(hex_len); 736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (hex) { 756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_snprintf_hex(hex, hex_len, buf, len); 766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_msg(hapd->msg_ctx, MSG_INFO, 776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "EAPOL-TX " MACSTR " %s", 786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MAC2STR(sta->addr), hex); 796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(hex); 806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else 826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */ 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->flags & WLAN_STA_PREAUTH) { 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_send(hapd, sta, buf, len); 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 86a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt hostapd_drv_hapd_send_eapol( 87a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt hapd, sta->addr, buf, len, 88a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt encrypt, hostapd_sta_flags_to_drv(sta->flags)); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_set_sta_authorized(struct hostapd_data *hapd, 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, int authorized) 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->flags & WLAN_STA_PREAUTH) 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (authorized) { 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_sta_set_authorized(hapd, sta, 1); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = hostapd_set_authorized(hapd, sta, 1); 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "authorizing port"); 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_sta_set_authorized(hapd, sta, 0); 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = hostapd_set_authorized(hapd, sta, 0); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "unauthorizing port"); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res && errno != ENOENT) { 1169657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt wpa_printf(MSG_DEBUG, "Could not set station " MACSTR 1179657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt " flags for kernel driver (errno=%d).", 1189657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt MAC2STR(sta->addr), errno); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 121d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (authorized) { 12204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt os_get_reltime(&sta->connected_time); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt accounting_sta_start(hapd, sta); 124d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_tx_key_one(struct hostapd_data *hapd, 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int idx, int broadcast, 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key_data, size_t key_len) 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *ekey; 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *hdr; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_eapol_key *key; 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, ekey_len; 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = sizeof(*key) + key_len; 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(sizeof(*hdr) + len); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee802_1x_hdr *) buf; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (struct ieee802_1x_eapol_key *) (hdr + 1); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->type = EAPOL_KEY_TYPE_RC4; 15061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt WPA_PUT_BE16(key->key_length, key_len); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_get_ntp_timestamp(key->replay_counter); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(key->key_iv, sizeof(key->key_iv))) { 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not get random numbers"); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_index = idx | (broadcast ? 0 : BIT(7)); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->eapol_key_index_workaround) { 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* According to some information, WinXP Supplicant seems to 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * interpret bit7 as an indication whether the key is to be 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * activated, so make it possible to enable workaround that 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * sets this bit for all keys. */ 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_index |= BIT(7); 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Key is encrypted using "Key-IV + MSK[0..31]" as the RC4-key and 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * MSK[32..63] is used to sign the message. */ 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_if->eapKeyData == NULL || sm->eap_if->eapKeyDataLen < 64) { 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "No eapKeyData available for encrypting " 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "and signing EAPOL-Key"); 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy((u8 *) (key + 1), key_data, key_len); 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ekey_len = sizeof(key->key_iv) + 32; 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ekey = os_malloc(ekey_len); 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ekey == NULL) { 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not encrypt key"); 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ekey, key->key_iv, sizeof(key->key_iv)); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ekey + sizeof(key->key_iv), sm->eap_if->eapKeyData, 32); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rc4_skip(ekey, ekey_len, 0, (u8 *) (key + 1), key_len); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ekey); 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* This header is needed here for HMAC-MD5, but it will be regenerated 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * in ieee802_1x_send() */ 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->version = hapd->conf->eapol_version; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->length = host_to_be16(len); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_md5(sm->eap_if->eapKeyData + 32, 32, buf, sizeof(*hdr) + len, 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_signature); 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Sending EAPOL-Key to " MACSTR 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " (%s index=%d)", MAC2STR(sm->addr), 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt broadcast ? "broadcast" : "unicast", idx); 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_send(hapd, sta, IEEE802_1X_TYPE_EAPOL_KEY, (u8 *) key, len); 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->eapol_sm) 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->dot1xAuthEapolFramesTx++; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta) 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_authenticator *eapol = hapd->eapol_auth; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL || !sm->eap_if->eapKeyData) 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Sending EAPOL-Key(s) to " MACSTR, 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sta->addr)); 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_VLAN 2195393a0f77c5281735888bd9dcf8d8abeb5961461Dmitry Shmidt if (sta->vlan_id > 0 && sta->vlan_id <= MAX_VLAN_ID) { 2205393a0f77c5281735888bd9dcf8d8abeb5961461Dmitry Shmidt wpa_printf(MSG_ERROR, "Using WEP with vlans is not supported."); 2215393a0f77c5281735888bd9dcf8d8abeb5961461Dmitry Shmidt return; 2225393a0f77c5281735888bd9dcf8d8abeb5961461Dmitry Shmidt } 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_VLAN */ 2245393a0f77c5281735888bd9dcf8d8abeb5961461Dmitry Shmidt 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eapol->default_wep_key) { 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_tx_key_one(hapd, sta, eapol->default_wep_key_idx, 1, 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key, 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->default_wep_key_len); 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->individual_wep_key_len > 0) { 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *ikey; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikey = os_malloc(hapd->conf->individual_wep_key_len); 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikey == NULL || 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt random_get_bytes(ikey, hapd->conf->individual_wep_key_len)) 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not generate random " 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "individual WEP key."); 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ikey); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "Individual WEP key", 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikey, hapd->conf->individual_wep_key_len); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_tx_key_one(hapd, sta, 0, 0, ikey, 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->individual_wep_key_len); 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: set encryption in TX callback, i.e., only after STA 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * has ACKed EAPOL-Key frame */ 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->addr, 0, 1, NULL, 0, ikey, 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->individual_wep_key_len)) { 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not set individual WEP " 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "encryption."); 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ikey); 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst char *radius_mode_txt(struct hostapd_data *hapd) 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hapd->iface->conf->hw_mode) { 266a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt case HOSTAPD_MODE_IEEE80211AD: 267a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return "802.11ad"; 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211A: 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "802.11a"; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211G: 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "802.11g"; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211B: 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "802.11b"; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta) 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rate = 0; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < sta->supported_rates_len; i++) 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((sta->supported_rates[i] & 0x7f) > rate) 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rate = sta->supported_rates[i] & 0x7f; 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return rate; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_learn_identity(struct hostapd_data *hapd, 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm, 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *eap, size_t len) 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity; 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len; 2996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const struct eap_hdr *hdr = (const struct eap_hdr *) eap; 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len <= sizeof(struct eap_hdr) || 3026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (hdr->code == EAP_CODE_RESPONSE && 3036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt eap[sizeof(struct eap_hdr)] != EAP_TYPE_IDENTITY) || 3046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (hdr->code == EAP_CODE_INITIATE && 3056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt eap[sizeof(struct eap_hdr)] != EAP_ERP_TYPE_REAUTH) || 3066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (hdr->code != EAP_CODE_RESPONSE && 3076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt hdr->code != EAP_CODE_INITIATE)) 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_identity(sm->eap, &identity_len); 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity == NULL) 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Save station identity for future RADIUS packets */ 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->identity); 3164b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt sm->identity = (u8 *) dup_binstr(identity, identity_len); 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->identity == NULL) { 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len = 0; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len = identity_len; 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X, 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "STA identity '%s'", sm->identity); 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolRespIdFramesRx++; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32903658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidtstatic int add_common_radius_sta_attr_rsn(struct hostapd_data *hapd, 33003658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt struct hostapd_radius_attr *req_attr, 33103658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt struct sta_info *sta, 33203658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt struct radius_msg *msg) 33303658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt{ 33403658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt u32 suite; 33503658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt int ver, val; 33603658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt 33703658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt ver = wpa_auth_sta_wpa_version(sta->wpa_sm); 33803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt val = wpa_auth_get_pairwise(sta->wpa_sm); 33903658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt suite = wpa_cipher_to_suite(ver, val); 34003658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (val != -1 && 34103658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt !hostapd_config_get_radius_attr(req_attr, 34203658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt RADIUS_ATTR_WLAN_PAIRWISE_CIPHER) && 34303658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt !radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_PAIRWISE_CIPHER, 34403658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt suite)) { 34503658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add WLAN-Pairwise-Cipher"); 34603658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return -1; 34703658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt } 34803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt 3494171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt suite = wpa_cipher_to_suite(((hapd->conf->wpa & 0x2) || 3504171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt hapd->conf->osen) ? 35103658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt WPA_PROTO_RSN : WPA_PROTO_WPA, 35203658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt hapd->conf->wpa_group); 35303658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (!hostapd_config_get_radius_attr(req_attr, 35403658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt RADIUS_ATTR_WLAN_GROUP_CIPHER) && 35503658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt !radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_GROUP_CIPHER, 35603658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt suite)) { 35703658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add WLAN-Group-Cipher"); 35803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return -1; 35903658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt } 36003658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt 36103658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt val = wpa_auth_sta_key_mgmt(sta->wpa_sm); 36203658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt suite = wpa_akm_to_suite(val); 36303658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (val != -1 && 36403658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt !hostapd_config_get_radius_attr(req_attr, 36503658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt RADIUS_ATTR_WLAN_AKM_SUITE) && 36603658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt !radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_AKM_SUITE, 36703658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt suite)) { 36803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add WLAN-AKM-Suite"); 36903658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return -1; 37003658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt } 37103658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt 37203658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt#ifdef CONFIG_IEEE80211W 37303658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 37403658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt suite = wpa_cipher_to_suite(WPA_PROTO_RSN, 37503658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt hapd->conf->group_mgmt_cipher); 37603658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (!hostapd_config_get_radius_attr( 37703658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt req_attr, RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER) && 37803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt !radius_msg_add_attr_int32( 37903658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt msg, RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER, suite)) { 38003658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt wpa_printf(MSG_ERROR, 38103658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt "Could not add WLAN-Group-Mgmt-Cipher"); 38203658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return -1; 38303658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt } 38403658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt } 38503658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 38603658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt 38703658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return 0; 38803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt} 38903658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt 39003658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt 39161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int add_common_radius_sta_attr(struct hostapd_data *hapd, 39261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct hostapd_radius_attr *req_attr, 39361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct sta_info *sta, 39461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct radius_msg *msg) 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[128]; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!hostapd_config_get_radius_attr(req_attr, 39961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt RADIUS_ATTR_NAS_PORT) && 40061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt !radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) { 40161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add NAS-Port"); 40261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 40361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, 40661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt MAC2STR(sta->addr)); 40761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt buf[sizeof(buf) - 1] = '\0'; 40861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, 40961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt (u8 *) buf, os_strlen(buf))) { 41061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add Calling-Station-Id"); 41161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 41261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 41461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sta->flags & WLAN_STA_PREAUTH) { 41561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_strlcpy(buf, "IEEE 802.11i Pre-Authentication", 41661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sizeof(buf)); 41761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else { 41861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s", 41961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt radius_sta_rate(hapd, sta) / 2, 42061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt (radius_sta_rate(hapd, sta) & 1) ? ".5" : "", 42161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt radius_mode_txt(hapd)); 42261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt buf[sizeof(buf) - 1] = '\0'; 42361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 42461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!hostapd_config_get_radius_attr(req_attr, 42561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt RADIUS_ATTR_CONNECT_INFO) && 42661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt !radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, 42761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt (u8 *) buf, os_strlen(buf))) { 42861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add Connect-Info"); 42961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 432a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (sta->acct_session_id_hi || sta->acct_session_id_lo) { 433a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_snprintf(buf, sizeof(buf), "%08X-%08X", 434a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt sta->acct_session_id_hi, sta->acct_session_id_lo); 435a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (!radius_msg_add_attr(msg, RADIUS_ATTR_ACCT_SESSION_ID, 436a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt (u8 *) buf, os_strlen(buf))) { 437a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add Acct-Session-Id"); 438a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 439a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 440a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 441a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 44203658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt#ifdef CONFIG_IEEE80211R 44303658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) && 44403658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt sta->wpa_sm && 44503658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt (wpa_key_mgmt_ft(wpa_auth_sta_key_mgmt(sta->wpa_sm)) || 44603658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt sta->auth_alg == WLAN_AUTH_FT) && 44703658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt !hostapd_config_get_radius_attr(req_attr, 44803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt RADIUS_ATTR_MOBILITY_DOMAIN_ID) && 44903658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt !radius_msg_add_attr_int32(msg, RADIUS_ATTR_MOBILITY_DOMAIN_ID, 45003658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt WPA_GET_BE16( 45103658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt hapd->conf->mobility_domain))) { 45203658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add Mobility-Domain-Id"); 45303658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return -1; 45403658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt } 45503658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 45603658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt 4574171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt if ((hapd->conf->wpa || hapd->conf->osen) && sta->wpa_sm && 45803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt add_common_radius_sta_attr_rsn(hapd, req_attr, sta, msg) < 0) 45903658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return -1; 46003658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt 46161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 46261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 46561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint add_common_radius_attr(struct hostapd_data *hapd, 46661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct hostapd_radius_attr *req_attr, 46761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct sta_info *sta, 46861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct radius_msg *msg) 46961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 47061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt char buf[128]; 47161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct hostapd_radius_attr *attr; 47261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 47361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!hostapd_config_get_radius_attr(req_attr, 47404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt RADIUS_ATTR_NAS_IP_ADDRESS) && 47504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hapd->conf->own_ip_addr.af == AF_INET && 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) { 47861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add NAS-IP-Address"); 47961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 48361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!hostapd_config_get_radius_attr(req_attr, 48404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt RADIUS_ATTR_NAS_IPV6_ADDRESS) && 48504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hapd->conf->own_ip_addr.af == AF_INET6 && 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) { 48861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add NAS-IPv6-Address"); 48961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!hostapd_config_get_radius_attr(req_attr, 49404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt RADIUS_ATTR_NAS_IDENTIFIER) && 49504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hapd->conf->nas_identifier && 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) hapd->conf->nas_identifier, 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(hapd->conf->nas_identifier))) { 49961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add NAS-Identifier"); 50061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", 50461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt MAC2STR(hapd->own_addr), 50561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_ssid_txt(hapd->conf->ssid.ssid, 50661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt hapd->conf->ssid.ssid_len)); 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[sizeof(buf) - 1] = '\0'; 50861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!hostapd_config_get_radius_attr(req_attr, 50904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt RADIUS_ATTR_CALLED_STATION_ID) && 51004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt !radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) buf, os_strlen(buf))) { 51261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add Called-Station-Id"); 51361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!hostapd_config_get_radius_attr(req_attr, 51761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt RADIUS_ATTR_NAS_PORT_TYPE) && 51861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt !radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, 51961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { 52061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add NAS-Port-Type"); 52161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 52261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 52361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 52403658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt#ifdef CONFIG_INTERWORKING 52503658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (hapd->conf->interworking && 52603658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt !is_zero_ether_addr(hapd->conf->hessid)) { 52703658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, 52803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt MAC2STR(hapd->conf->hessid)); 52903658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt buf[sizeof(buf) - 1] = '\0'; 53003658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (!hostapd_config_get_radius_attr(req_attr, 53103658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt RADIUS_ATTR_WLAN_HESSID) && 53203658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt !radius_msg_add_attr(msg, RADIUS_ATTR_WLAN_HESSID, 53303658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt (u8 *) buf, os_strlen(buf))) { 53403658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add WLAN-HESSID"); 53503658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return -1; 53603658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt } 53703658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt } 53803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt#endif /* CONFIG_INTERWORKING */ 53903658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt 54061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sta && add_common_radius_sta_attr(hapd, req_attr, sta, msg) < 0) 54161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 54261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 54361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (attr = req_attr; attr; attr = attr->next) { 54461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!radius_msg_add_attr(msg, attr->type, 54561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_head(attr->val), 54661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_len(attr->val))) { 54761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add RADIUS " 54861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "attribute"); 54961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 55061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 55161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 55261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 55361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 55461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 55561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 55661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 55761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd, 55861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct sta_info *sta, 55961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const u8 *eap, size_t len) 56061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 56161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct radius_msg *msg; 56261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 56361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 56461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm == NULL) 56561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 56661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 56761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ieee802_1x_learn_identity(hapd, sm, eap, len); 56861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 56961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS " 57061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "packet"); 57161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 57261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->radius_identifier = radius_client_get_id(hapd->radius); 57361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, 57461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->radius_identifier); 57561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (msg == NULL) { 576cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "Could not create new RADIUS packet"); 57761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 57861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 57961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 58061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta)); 58161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 58261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->identity && 58361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, 58461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->identity, sm->identity_len)) { 585cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "Could not add User-Name"); 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (add_common_radius_attr(hapd, hapd->conf->radius_auth_req_attr, sta, 59061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt msg) < 0) 59161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto fail; 59261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: should probably check MTU from driver config; 2304 is max for 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE 802.11, but use 1400 to avoid problems with too large packets 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 59604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!hostapd_config_get_radius_attr(hapd->conf->radius_auth_req_attr, 59704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt RADIUS_ATTR_FRAMED_MTU) && 59804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt !radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) { 599cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "Could not add Framed-MTU"); 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6034171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt if (!radius_msg_add_eap(msg, eap, len)) { 604cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "Could not add EAP-Message"); 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* State attribute must be copied if and only if this packet is 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Access-Request reply to the previous Access-Challenge */ 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->last_recv_radius && 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_get_hdr(sm->last_recv_radius)->code == 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_CODE_ACCESS_CHALLENGE) { 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res = radius_msg_copy_attr(msg, sm->last_recv_radius, 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_ATTR_STATE); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 616cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "Could not copy State attribute from previous Access-Challenge"); 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res > 0) { 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Copied RADIUS State Attribute"); 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (hapd->conf->radius_request_cui) { 62504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *cui; 62604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt size_t cui_len; 62704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Add previously learned CUI or nul CUI to request CUI */ 62804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (sm->radius_cui) { 62904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cui = wpabuf_head(sm->radius_cui); 63004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cui_len = wpabuf_len(sm->radius_cui); 63104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else { 63204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cui = (const u8 *) "\0"; 63304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cui_len = 1; 63404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 63504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!radius_msg_add_attr(msg, 63604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, 63704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cui, cui_len)) { 63804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_ERROR, "Could not add CUI"); 63904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto fail; 64004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 64104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 64204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 643f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_HS20 644f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (hapd->conf->hs20) { 645f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u8 ver = 1; /* Release 2 */ 646f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!radius_msg_add_wfa( 647f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt msg, RADIUS_VENDOR_ATTR_WFA_HS20_AP_VERSION, 648f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt &ver, 1)) { 649f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add HS 2.0 AP " 650f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "version"); 651f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt goto fail; 652f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 653f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 654f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sta->hs20_ie && wpabuf_len(sta->hs20_ie) > 0) { 655f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt const u8 *pos; 656f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u8 buf[3]; 657f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u16 id; 658f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt pos = wpabuf_head_u8(sta->hs20_ie); 659f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt buf[0] = (*pos) >> 4; 660f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (((*pos) & HS20_PPS_MO_ID_PRESENT) && 661f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_len(sta->hs20_ie) >= 3) 662f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt id = WPA_GET_LE16(pos + 1); 663f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt else 664f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt id = 0; 665f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt WPA_PUT_BE16(buf + 1, id); 666f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!radius_msg_add_wfa( 667f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt msg, 668f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt RADIUS_VENDOR_ATTR_WFA_HS20_STA_VERSION, 669f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt buf, sizeof(buf))) { 670f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not add HS 2.0 " 671f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "STA version"); 672f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt goto fail; 673f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 674f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 675f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 676f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_HS20 */ 677f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, sta->addr) < 0) 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fail: 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(msg); 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_eap_response(struct hostapd_data *hapd, 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, struct eap_hdr *eap, 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len) 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 type, *data; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = (u8 *) (eap + 1); 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < sizeof(*eap) + 1) { 701cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "handle_eap_response: too short response data"); 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_type_supp = type = data[0]; 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X, 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d " 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "id=%d len=%d) from STA: EAP Response-%s (%d)", 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->code, eap->identifier, be_to_host16(eap->length), 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_get_name(0, type), type); 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolRespFramesRx++; 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(sm->eap_if->eapRespData); 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len); 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eapolEap = TRUE; 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void handle_eap_initiate(struct hostapd_data *hapd, 7226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct sta_info *sta, struct eap_hdr *eap, 7236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t len) 7246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 7256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_ERP 7266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u8 type, *data; 7276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 7286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 7296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (sm == NULL) 7306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return; 7316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 7326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (len < sizeof(*eap) + 1) { 7336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_INFO, 7346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "handle_eap_initiate: too short response data"); 7356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return; 7366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 7386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt data = (u8 *) (eap + 1); 7396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt type = data[0]; 7406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 7416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X, 7426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d " 7436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "id=%d len=%d) from STA: EAP Initiate type %u", 7446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt eap->code, eap->identifier, be_to_host16(eap->length), 7456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt type); 7466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 7476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpabuf_free(sm->eap_if->eapRespData); 7486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len); 7496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sm->eapolEap = TRUE; 7506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_ERP */ 7516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 7526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 7536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Process incoming EAP packet from Supplicant */ 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_eap(struct hostapd_data *hapd, struct sta_info *sta, 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, size_t len) 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *eap; 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 eap_len; 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < sizeof(*eap)) { 762cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, " too short EAP packet"); 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = (struct eap_hdr *) buf; 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_len = be_to_host16(eap->length); 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP: code=%d identifier=%d length=%d", 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->code, eap->identifier, eap_len); 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_len < sizeof(*eap)) { 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " Invalid EAP length"); 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (eap_len > len) { 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " Too short frame to contain this EAP " 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "packet"); 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (eap_len < len) { 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " Ignoring %lu extra bytes after EAP " 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "packet", (unsigned long) len - eap_len); 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (eap->code) { 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_REQUEST: 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " (request)"); 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_RESPONSE: 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " (response)"); 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handle_eap_response(hapd, sta, eap, eap_len); 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_SUCCESS: 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " (success)"); 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_FAILURE: 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " (failure)"); 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case EAP_CODE_INITIATE: 7986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, " (initiate)"); 7996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt handle_eap_initiate(hapd, sta, eap, eap_len); 8006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 8016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case EAP_CODE_FINISH: 8026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, " (finish)"); 8036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " (unknown code)"); 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eapol_state_machine * 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta) 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int flags = 0; 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->flags & WLAN_STA_PREAUTH) 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= EAPOL_SM_PREAUTH; 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->wpa_sm) { 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= EAPOL_SM_USES_WPA; 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_sta_get_pmksa(sta->wpa_sm)) 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= EAPOL_SM_FROM_PMKSA_CACHE; 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eapol_auth_alloc(hapd->eapol_auth, sta->addr, flags, 82361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sta->wps_ie, sta->p2p_ie, sta, 82461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sta->identity, sta->radius_cui); 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ieee802_1x_receive - Process the EAPOL frames from the Supplicant 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @hapd: hostapd BSS data 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sa: Source address (sender of the EAPOL frame) 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: EAPOL frame 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of buf in octets 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called for each incoming EAPOL frame from the interface 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len) 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta; 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *hdr; 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_eapol_key *key; 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 datalen; 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *pmksa; 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_mgmt; 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 847f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!hapd->conf->ieee802_1x && !hapd->conf->wpa && !hapd->conf->osen && 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !hapd->conf->wps_state) 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR, 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, MAC2STR(sa)); 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta = ap_get_sta(hapd, sa); 8541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!sta || (!(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH)) && 8551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED))) { 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not " 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "associated/Pre-authenticating STA"); 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < sizeof(*hdr)) { 862cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, " too short IEEE 802.1X packet"); 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee802_1x_hdr *) buf; 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt datalen = be_to_host16(hdr->length); 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " IEEE 802.1X: version=%d type=%d length=%d", 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->version, hdr->type, datalen); 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len - sizeof(*hdr) < datalen) { 872cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, " frame too short for this IEEE 802.1X packet"); 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->eapol_sm) 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->dot1xAuthEapLengthErrorFramesRx++; 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len - sizeof(*hdr) > datalen) { 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " ignoring %lu extra octets after " 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IEEE 802.1X packet", 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len - sizeof(*hdr) - datalen); 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->eapol_sm) { 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->dot1xAuthLastEapolFrameVersion = hdr->version; 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->dot1xAuthEapolFramesRx++; 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (struct ieee802_1x_eapol_key *) (hdr + 1); 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (datalen >= sizeof(struct ieee802_1x_eapol_key) && 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->type == IEEE802_1X_TYPE_EAPOL_KEY && 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key->type == EAPOL_KEY_TYPE_WPA || 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->type == EAPOL_KEY_TYPE_RSN)) { 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_receive(hapd->wpa_auth, sta->wpa_sm, (u8 *) hdr, 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*hdr) + datalen); 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 898f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!hapd->conf->ieee802_1x && !hapd->conf->osen && 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) { 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - " 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "802.1X not enabled and WPS not used"); 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm); 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) { 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - " 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "STA is using PSK"); 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sta->eapol_sm) { 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta); 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sta->eapol_sm) 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 918f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!hapd->conf->ieee802_1x && hapd->conf->wps_state) { 9191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u32 wflags = sta->flags & (WLAN_STA_WPS | 9201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WLAN_STA_WPS2 | 9211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WLAN_STA_MAYBE_WPS); 9221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wflags == WLAN_STA_MAYBE_WPS || 9231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wflags == (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) { 9241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 9251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Delay EAPOL frame transmission until a 9261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * possible WPS STA initiates the handshake 9271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * with EAPOL-Start. Only allow the wait to be 9281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * skipped if the STA is known to support WPS 9291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 2.0. 9301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 9311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Do not start " 9321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "EAPOL until EAPOL-Start is " 9331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "received"); 9341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sta->eapol_sm->flags |= EAPOL_SM_WAIT_START; 9351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->eap_if->portEnabled = TRUE; 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* since we support version 1, we can ignore version field and proceed 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * as specified in version 1 standard [IEEE Std 802.1X-2001, 7.5.5] */ 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: actually, we are not version 1 anymore.. However, Version 2 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * does not change frame contents, so should be ok to process frames 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * more or less identically. Some changes might be needed for 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * verification of fields. */ 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hdr->type) { 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE802_1X_TYPE_EAP_PACKET: 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handle_eap(hapd, sta, (u8 *) (hdr + 1), datalen); 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE802_1X_TYPE_EAPOL_START: 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "received EAPOL-Start " 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from STA"); 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START; 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm); 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa) { 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "cached PMKSA " 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "available - ignore it since " 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "STA sent EAPOL-Start"); 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_sta_clear_pmksa(sta->wpa_sm, pmksa); 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->eapolStart = TRUE; 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->dot1xAuthEapolStartFramesRx++; 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_clear_identity(sta->eapol_sm->eap); 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL); 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE802_1X_TYPE_EAPOL_LOGOFF: 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "received EAPOL-Logoff " 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from STA"); 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->acct_terminate_cause = 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt accounting_sta_stop(hapd, sta); 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->eapolLogoff = TRUE; 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++; 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_clear_identity(sta->eapol_sm->eap); 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE802_1X_TYPE_EAPOL_KEY: 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " EAPOL-Key"); 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ap_sta_is_authorized(sta)) { 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " Dropped key data from " 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unauthorized Supplicant"); 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT: 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " EAPOL-Encapsulated-ASF-Alert"); 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: implement support for this; show data */ 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " unknown IEEE 802.1X packet type"); 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->dot1xAuthInvalidEapolFramesRx++; 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_auth_step(sta->eapol_sm); 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ieee802_1x_new_station - Start IEEE 802.1X authentication 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @hapd: hostapd BSS data 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sta: The station 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to start IEEE 802.1X authentication when a new 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * station completes IEEE 802.11 association. 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *pmksa; 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int reassoc = 1; 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int force_1x = 0; 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_mgmt; 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 10256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (hapd->conf->wps_state && 10266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ((hapd->conf->wpa && (sta->flags & WLAN_STA_MAYBE_WPS)) || 10276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (sta->flags & WLAN_STA_WPS))) { 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Need to enable IEEE 802.1X/EAPOL state machines for possible 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPS handshake even if IEEE 802.1X/EAPOL is not used for 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication in this BSS. 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt force_1x = 1; 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1037f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!force_1x && !hapd->conf->ieee802_1x && !hapd->conf->osen) { 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - " 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "802.1X not enabled or forced for WPS"); 104004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 104104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Clear any possible EAPOL authenticator state to support 104204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * reassociation change from WPS to PSK. 104304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 104404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ieee802_1x_free_station(sta); 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm); 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) { 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - using PSK"); 105104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 105204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Clear any possible EAPOL authenticator state to support 105304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * reassociation change from WPA-EAP to PSK. 105404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 105504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ieee802_1x_free_station(sta); 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->eapol_sm == NULL) { 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "start authentication"); 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta); 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->eapol_sm == NULL) { 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_MODULE_IEEE8021X, 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_INFO, 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed to allocate state machine"); 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reassoc = 0; 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START; 1075f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!hapd->conf->ieee802_1x && hapd->conf->wps_state && 1076f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt !(sta->flags & WLAN_STA_WPS2)) { 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 10781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Delay EAPOL frame transmission until a possible WPS STA 10791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * initiates the handshake with EAPOL-Start. Only allow the 10801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * wait to be skipped if the STA is known to support WPS 2.0. 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Do not start EAPOL until " 10831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "EAPOL-Start is received"); 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->flags |= EAPOL_SM_WAIT_START; 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->eap_if->portEnabled = TRUE; 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->auth_alg == WLAN_AUTH_FT) { 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PMK from FT - skip IEEE 802.1X/EAP"); 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Setup EAPOL state machines to already authenticated state 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * because of existing FT information from R0KH. */ 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->keyRun = TRUE; 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->authSuccess = TRUE; 1102c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sta->eapol_sm->authFail = FALSE; 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->eapol_sm->eap) 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_notify_cached(sta->eapol_sm->eap); 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: get vlan_id from R0KH using RRB message */ 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm); 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa) { 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PMK from PMKSA cache - skip IEEE 802.1X/EAP"); 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Setup EAPOL state machines to already authenticated state 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * because of existing PMKSA information in the cache. */ 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->keyRun = TRUE; 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->authSuccess = TRUE; 1122c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sta->eapol_sm->authFail = FALSE; 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->eapol_sm->eap) 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_notify_cached(sta->eapol_sm->eap); 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_to_eapol_data(pmksa, sta->eapol_sm); 11268347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt ap_sta_bind_vlan(hapd, sta); 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reassoc) { 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Force EAPOL state machines to start 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * re-authentication without having to wait for the 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Supplicant to send EAPOL-Start. 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->reAuthenticate = TRUE; 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_auth_step(sta->eapol_sm); 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_free_station(struct sta_info *sta) 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm = NULL; 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(sm->last_recv_radius); 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_free_class(&sm->radius_class); 115304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(sm->radius_cui); 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->identity); 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_auth_free(sm); 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd, 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta) 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 116561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct wpabuf *eap; 116661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const struct eap_hdr *hdr; 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int eap_type = -1; 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[64]; 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg; 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL || sm->last_recv_radius == NULL) { 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm) 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapNoReq = TRUE; 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = sm->last_recv_radius; 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt eap = radius_msg_get_eap(msg); 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) { 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RFC 3579, Chap. 2.6.3: 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * attribute */ 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_WARNING, "could not extract " 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-Message from RADIUS message"); 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapNoReq = TRUE; 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 119261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpabuf_len(eap) < sizeof(*hdr)) { 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_WARNING, "too short EAP packet " 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received from authentication server"); 119661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_free(eap); 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapNoReq = TRUE; 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 120161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (wpabuf_len(eap) > sizeof(*hdr)) 120261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt eap_type = (wpabuf_head_u8(eap))[sizeof(*hdr)]; 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 120461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt hdr = wpabuf_head(eap); 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hdr->code) { 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_REQUEST: 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_type >= 0) 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_type_authsrv = eap_type; 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)", 12102f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt eap_server_get_name(0, eap_type), eap_type); 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_RESPONSE: 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)", 12142f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt eap_server_get_name(0, eap_type), eap_type); 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_SUCCESS: 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(buf, "EAP Success", sizeof(buf)); 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_FAILURE: 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(buf, "EAP Failure", sizeof(buf)); 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(buf, "unknown EAP code", sizeof(buf)); 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[sizeof(buf) - 1] = '\0'; 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "decapsulated EAP packet (code=%d " 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "id=%d len=%d) from RADIUS server: %s", 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->code, hdr->identifier, be_to_host16(hdr->length), 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf); 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapReq = TRUE; 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(sm->eap_if->aaaEapReqData); 123561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->eap_if->aaaEapReqData = eap; 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_get_keys(struct hostapd_data *hapd, 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, struct radius_msg *msg, 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *req, 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *shared_secret, 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t shared_secret_len) 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_ms_mppe_keys *keys; 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys = radius_msg_get_ms_keys(msg, req, shared_secret, 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt shared_secret_len); 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys && keys->send && keys->recv) { 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len = keys->send_len + keys->recv_len; 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "MS-MPPE-Send-Key", 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->send, keys->send_len); 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "MS-MPPE-Recv-Key", 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->recv, keys->recv_len); 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->eap_if->aaaEapKeyData); 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapKeyData = os_malloc(len); 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_if->aaaEapKeyData) { 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->eap_if->aaaEapKeyData, keys->recv, 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->recv_len); 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->eap_if->aaaEapKeyData + keys->recv_len, 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->send, keys->send_len); 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapKeyDataLen = len; 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapKeyAvailable = TRUE; 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1270807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } else { 1271807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_printf(MSG_DEBUG, 1272807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt "MS-MPPE: 1x_get_keys, could not get keys: %p send: %p recv: %p", 1273807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt keys, keys ? keys->send : NULL, 1274807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt keys ? keys->recv : NULL); 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys) { 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->send); 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->recv); 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys); 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_store_radius_class(struct hostapd_data *hapd, 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg) 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12891d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt u8 *attr_class; 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t class_len; 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int count, i; 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_attr_data *nclass; 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t nclass_count; 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!hapd->conf->radius->acct_server || hapd->radius == NULL || 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm == NULL) 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_free_class(&sm->radius_class); 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = radius_msg_count_attr(msg, RADIUS_ATTR_CLASS, 1); 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (count <= 0) 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 130561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt nclass = os_calloc(count, sizeof(struct radius_attr_data)); 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nclass == NULL) 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nclass_count = 0; 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13111d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt attr_class = NULL; 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < count; i++) { 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt do { 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CLASS, 13151d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt &attr_class, &class_len, 13161d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt attr_class) < 0) { 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i = count; 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } while (class_len < 1); 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nclass[nclass_count].data = os_malloc(class_len); 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nclass[nclass_count].data == NULL) 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13261d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt os_memcpy(nclass[nclass_count].data, attr_class, class_len); 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nclass[nclass_count].len = class_len; 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nclass_count++; 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->radius_class.attr = nclass; 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->radius_class.count = nclass_count; 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Stored %lu RADIUS Class " 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "attributes for " MACSTR, 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) sm->radius_class.count, 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sta->addr)); 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Update sta->identity based on User-Name attribute in Access-Accept */ 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_update_sta_identity(struct hostapd_data *hapd, 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg) 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *identity; 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, &buf, &len, 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL) < 0) 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13564b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt identity = (u8 *) dup_binstr(buf, len); 13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity == NULL) 13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "old identity '%s' updated with " 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "User-Name from Access-Accept '%s'", 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity ? (char *) sm->identity : "N/A", 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (char *) identity); 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->identity); 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity = identity; 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len = len; 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 137204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt/* Update CUI based on Chargeable-User-Identity attribute in Access-Accept */ 137304949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void ieee802_1x_update_sta_cui(struct hostapd_data *hapd, 137404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct sta_info *sta, 137504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct radius_msg *msg) 137604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 137704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 137804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf *cui; 137904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 *buf; 138004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt size_t len; 138104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 138204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (sm == NULL) 138304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 138404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 138504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, 138604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt &buf, &len, NULL) < 0) 138704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 138804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 138904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt cui = wpabuf_alloc_copy(buf, len); 139004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (cui == NULL) 139104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 139204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 139304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(sm->radius_cui); 139404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sm->radius_cui = cui; 139504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 139604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 139704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 1398f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_HS20 1399f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1400f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic void ieee802_1x_hs20_sub_rem(struct sta_info *sta, u8 *pos, size_t len) 1401f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 1402f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->remediation = 1; 1403f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt os_free(sta->remediation_url); 1404f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (len > 2) { 1405f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->remediation_url = os_malloc(len); 1406f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!sta->remediation_url) 1407f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return; 1408f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->remediation_method = pos[0]; 1409f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt os_memcpy(sta->remediation_url, pos + 1, len - 1); 1410f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->remediation_url[len - 1] = '\0'; 1411f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "HS 2.0: Subscription remediation needed " 1412f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "for " MACSTR " - server method %u URL %s", 1413f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MAC2STR(sta->addr), sta->remediation_method, 1414f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->remediation_url); 1415f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else { 1416f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->remediation_url = NULL; 1417f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "HS 2.0: Subscription remediation needed " 1418f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "for " MACSTR, MAC2STR(sta->addr)); 1419f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1420f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* TODO: assign the STA into remediation VLAN or add filtering */ 1421f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 1422f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1423f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1424f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic void ieee802_1x_hs20_deauth_req(struct hostapd_data *hapd, 1425f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct sta_info *sta, u8 *pos, 1426f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt size_t len) 1427f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 1428f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (len < 3) 1429f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return; /* Malformed information */ 1430f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->hs20_deauth_requested = 1; 1431f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "HS 2.0: Deauthentication request - Code %u " 1432f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "Re-auth Delay %u", 1433f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt *pos, WPA_GET_LE16(pos + 1)); 1434f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_free(sta->hs20_deauth_req); 1435f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->hs20_deauth_req = wpabuf_alloc(len + 1); 1436f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sta->hs20_deauth_req) { 1437f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_data(sta->hs20_deauth_req, pos, 3); 1438f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_u8(sta->hs20_deauth_req, len - 3); 1439f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpabuf_put_data(sta->hs20_deauth_req, pos + 3, len - 3); 1440f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1441f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ap_sta_session_timeout(hapd, sta, hapd->conf->hs20_deauth_req_timeout); 1442f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 1443f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1444f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1445f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic void ieee802_1x_hs20_session_info(struct hostapd_data *hapd, 1446f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct sta_info *sta, u8 *pos, 1447f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt size_t len, int session_timeout) 1448f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 1449f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt unsigned int swt; 1450f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int warning_time, beacon_int; 1451f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1452f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (len < 1) 1453f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return; /* Malformed information */ 1454f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt os_free(sta->hs20_session_info_url); 1455f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->hs20_session_info_url = os_malloc(len); 1456f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sta->hs20_session_info_url == NULL) 1457f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return; 1458f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt swt = pos[0]; 1459f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt os_memcpy(sta->hs20_session_info_url, pos + 1, len - 1); 1460f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->hs20_session_info_url[len - 1] = '\0'; 1461f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "HS 2.0: Session Information URL='%s' SWT=%u " 1462f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "(session_timeout=%d)", 1463f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->hs20_session_info_url, swt, session_timeout); 1464f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (session_timeout < 0) { 1465f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "HS 2.0: No Session-Timeout set - ignore session info URL"); 1466f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return; 1467f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1468f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (swt == 255) 1469f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt swt = 1; /* Use one minute as the AP selected value */ 1470f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1471f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if ((unsigned int) session_timeout < swt * 60) 1472f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt warning_time = 0; 1473f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt else 1474f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt warning_time = session_timeout - swt * 60; 1475f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1476f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt beacon_int = hapd->iconf->beacon_int; 1477f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (beacon_int < 1) 1478f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt beacon_int = 100; /* best guess */ 1479f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->hs20_disassoc_timer = swt * 60 * 1000 / beacon_int * 125 / 128; 1480f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sta->hs20_disassoc_timer > 65535) 1481f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->hs20_disassoc_timer = 65535; 1482f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1483f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ap_sta_session_warning_timeout(hapd, sta, warning_time); 1484f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 1485f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1486f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_HS20 */ 1487f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1488f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1489f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic void ieee802_1x_check_hs20(struct hostapd_data *hapd, 1490f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct sta_info *sta, 1491f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct radius_msg *msg, 1492f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int session_timeout) 1493f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 1494f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_HS20 1495f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt u8 *buf, *pos, *end, type, sublen; 1496f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt size_t len; 1497f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1498f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt buf = NULL; 1499f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->remediation = 0; 1500f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->hs20_deauth_requested = 0; 1501f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1502f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (;;) { 1503f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_VENDOR_SPECIFIC, 1504f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt &buf, &len, buf) < 0) 1505f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt break; 1506f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (len < 6) 1507f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1508f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt pos = buf; 1509f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt end = buf + len; 1510f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (WPA_GET_BE32(pos) != RADIUS_VENDOR_ID_WFA) 1511f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 1512f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt pos += 4; 1513f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1514f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt type = *pos++; 1515f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sublen = *pos++; 1516f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sublen < 2) 1517f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; /* invalid length */ 1518f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sublen -= 2; /* skip header */ 1519f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (pos + sublen > end) 1520f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; /* invalid WFA VSA */ 1521f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1522f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt switch (type) { 1523f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt case RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION: 1524f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ieee802_1x_hs20_sub_rem(sta, pos, sublen); 1525f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt break; 1526f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt case RADIUS_VENDOR_ATTR_WFA_HS20_DEAUTH_REQ: 1527f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ieee802_1x_hs20_deauth_req(hapd, sta, pos, sublen); 1528f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt break; 1529f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt case RADIUS_VENDOR_ATTR_WFA_HS20_SESSION_INFO_URL: 1530f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ieee802_1x_hs20_session_info(hapd, sta, pos, sublen, 1531f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt session_timeout); 1532f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt break; 1533f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1534f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 1535f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_HS20 */ 1536f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 1537f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 1538f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct sta_id_search { 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 identifier; 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm; 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee802_1x_select_radius_identifier(struct hostapd_data *hapd, 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx) 15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_id_search *id_search = ctx; 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm && sm->radius_identifier >= 0 && 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->radius_identifier == id_search->identifier) { 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id_search->sm = sm; 15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eapol_state_machine * 15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtieee802_1x_search_radius_identifier(struct hostapd_data *hapd, u8 identifier) 15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_id_search id_search; 15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id_search.identifier = identifier; 15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id_search.sm = NULL; 15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_for_each_sta(hapd, ieee802_1x_select_radius_identifier, &id_search); 15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return id_search.sm; 15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ieee802_1x_receive_auth - Process RADIUS frames from Authentication Server 15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg: RADIUS response message 15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @req: RADIUS request message 15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @shared_secret: RADIUS shared secret 15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @shared_secret_len: Length of shared_secret in octets 15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Context data (struct hostapd_data *) 15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Processing status 15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic RadiusRxResult 15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, 15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *shared_secret, size_t shared_secret_len, 15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *data) 15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = data; 15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta; 15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 session_timeout = 0, termination_action, acct_interim_interval; 15898347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt int session_timeout_set, vlan_id = 0; 15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm; 15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int override_eapReq = 0; 15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_hdr *hdr = radius_msg_get_hdr(msg); 15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm = ieee802_1x_search_radius_identifier(hapd, hdr->identifier); 15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) { 15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Could not find matching " 15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "station for this RADIUS message"); 15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RADIUS_RX_UNKNOWN; 15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta = sm->sta; 16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be 16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * present when packet contains an EAP-Message attribute */ 16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->code == RADIUS_CODE_ACCESS_REJECT && 16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL, 16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) < 0 && 16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) { 16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Allowing RADIUS Access-Reject without " 16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Message-Authenticator since it does not include " 16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-Message"); 16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (radius_msg_verify(msg, shared_secret, shared_secret_len, 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req, 1)) { 1613cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have correct Message-Authenticator - dropped"); 16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RADIUS_RX_INVALID_AUTHENTICATOR; 16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT && 16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->code != RADIUS_CODE_ACCESS_REJECT && 16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) { 1620cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "Unknown RADIUS message code"); 16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RADIUS_RX_UNKNOWN; 16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->radius_identifier = -1; 16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RADIUS packet matching with station " MACSTR, 16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sta->addr)); 16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(sm->last_recv_radius); 16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->last_recv_radius = msg; 16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt session_timeout_set = 16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, 16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &session_timeout); 16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_TERMINATION_ACTION, 16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &termination_action)) 16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt termination_action = RADIUS_TERMINATION_ACTION_DEFAULT; 16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->acct_interim_interval == 0 && 16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->code == RADIUS_CODE_ACCESS_ACCEPT && 16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL, 16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &acct_interim_interval) == 0) { 16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (acct_interim_interval < 60) { 16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, 16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_MODULE_IEEE8021X, 16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_INFO, 16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ignored too small " 16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Acct-Interim-Interval %d", 16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt acct_interim_interval); 16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->acct_interim_interval = acct_interim_interval; 16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hdr->code) { 16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_CODE_ACCESS_ACCEPT: 16569d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED) 16578347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt vlan_id = 0; 16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_VLAN 16598347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt else 16608347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt vlan_id = radius_msg_get_vlanid(msg); 16618347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt if (vlan_id > 0 && 16628347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt hostapd_vlan_id_valid(hapd->conf->vlan, vlan_id)) { 16638347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt hostapd_logger(hapd, sta->addr, 16648347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt HOSTAPD_MODULE_RADIUS, 16658347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt HOSTAPD_LEVEL_INFO, 16668347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt "VLAN ID %d", vlan_id); 16678347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt } else if (vlan_id > 0) { 16688347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt sta->eapol_sm->authFail = TRUE; 16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, 16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_MODULE_RADIUS, 16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_INFO, 16728347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt "Invalid VLAN ID %d received from RADIUS server", 16738347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt vlan_id); 16748347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt break; 16759d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt } else if (hapd->conf->ssid.dynamic_vlan == 16769d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt DYNAMIC_VLAN_REQUIRED) { 16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->authFail = TRUE; 16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, 16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_MODULE_IEEE8021X, 16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_INFO, "authentication " 16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "server did not include required VLAN " 16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ID in Access-Accept"); 16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_VLAN */ 16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16878347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt sta->vlan_id = vlan_id; 16888347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt if ((sta->flags & WLAN_STA_ASSOC) && 16898347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt ap_sta_bind_vlan(hapd, sta) < 0) 16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16929ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt sta->session_timeout_set = !!session_timeout_set; 16939ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt sta->session_timeout = session_timeout; 16949ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt 16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RFC 3580, Ch. 3.17 */ 16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (session_timeout_set && termination_action == 16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_TERMINATION_ACTION_RADIUS_REQUEST) { 16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->reAuthPeriod = session_timeout; 16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (session_timeout_set) 17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_sta_session_timeout(hapd, sta, session_timeout); 17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaSuccess = TRUE; 17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt override_eapReq = 1; 17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_get_keys(hapd, sta, msg, req, shared_secret, 17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt shared_secret_len); 17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_store_radius_class(hapd, sta, msg); 17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_update_sta_identity(hapd, sta, msg); 170804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ieee802_1x_update_sta_cui(hapd, sta, msg); 1709f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ieee802_1x_check_hs20(hapd, sta, msg, 1710f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt session_timeout_set ? 1711f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt (int) session_timeout : -1); 1712f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sm->eap_if->eapKeyAvailable && !sta->remediation && 1713f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt !sta->hs20_deauth_requested && 17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_pmksa_add(sta->wpa_sm, sm->eapol_key_crypt, 17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt session_timeout_set ? 17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) session_timeout : -1, sm) == 0) { 17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, 17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Added PMKSA cache entry"); 17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_CODE_ACCESS_REJECT: 17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaFail = TRUE; 17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt override_eapReq = 1; 17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_CODE_ACCESS_CHALLENGE: 17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapReq = TRUE; 17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (session_timeout_set) { 17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RFC 2869, Ch. 2.3.2; RFC 3580, Ch. 3.17 */ 17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaMethodTimeout = session_timeout; 17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sm->addr, 17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_MODULE_IEEE8021X, 17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "using EAP timeout of %d seconds (from " 17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RADIUS)", 17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaMethodTimeout); 17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Use dynamic retransmission behavior per EAP 17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * specification. 17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaMethodTimeout = 0; 17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_decapsulate_radius(hapd, sta); 17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (override_eapReq) 17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapReq = FALSE; 17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_auth_step(sm); 17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RADIUS_RX_QUEUED; 17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta) 17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "aborting authentication"); 17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(sm->last_recv_radius); 17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->last_recv_radius = NULL; 17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_if->eapTimeout) { 17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Disconnect the STA since it did not reply to the last EAP 17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * request and we cannot continue EAP processing (EAP-Failure 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * could only be sent if the EAP peer actually replied). 17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 17781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "EAP Timeout, STA " MACSTR, 17791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(sta->addr)); 17801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->portEnabled = FALSE; 17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_sta_disconnect(hapd, sta, sta->addr, 17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_REASON_PREV_AUTH_NOT_VALID); 17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd) 17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_authenticator *eapol = hapd->eapol_auth; 17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->default_wep_key_len < 1) 17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(eapol->default_wep_key); 17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key = os_malloc(hapd->conf->default_wep_key_len); 17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eapol->default_wep_key == NULL || 17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt random_get_bytes(eapol->default_wep_key, 17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->default_wep_key_len)) { 1800cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "Could not generate random WEP key"); 18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(eapol->default_wep_key); 18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key = NULL; 18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IEEE 802.1X: New default WEP key", 18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key, 18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->default_wep_key_len); 18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee802_1x_sta_key_available(struct hostapd_data *hapd, 18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, void *ctx) 18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->eapol_sm) { 18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; 18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_auth_step(sta->eapol_sm); 18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx) 18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = eloop_ctx; 18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_authenticator *eapol = hapd->eapol_auth; 18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eapol->default_wep_key_idx >= 3) 18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key_idx = 18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->individual_wep_key_len > 0 ? 1 : 0; 18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key_idx++; 18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: New default WEP key index %d", 18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key_idx); 18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ieee802_1x_rekey_broadcast(hapd)) { 18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X, 18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_WARNING, "failed to generate a " 18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "new broadcast key"); 18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(eapol->default_wep_key); 18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key = NULL; 18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: Could setup key for RX here, but change default TX keyid only 18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * after new broadcast key has been sent to all stations. */ 18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, 18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt broadcast_ether_addr, 18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key_idx, 1, NULL, 0, 18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key, 18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->default_wep_key_len)) { 18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X, 18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_WARNING, "failed to configure a " 18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "new broadcast key"); 18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(eapol->default_wep_key); 18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key = NULL; 18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_for_each_sta(hapd, ieee802_1x_sta_key_available, NULL); 18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->wep_rekeying_period > 0) { 18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(hapd->conf->wep_rekeying_period, 0, 18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_rekey, hapd, NULL); 18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type, 18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t datalen) 18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta = sta_ctx; 18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) == 18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_STA_MAYBE_WPS) { 18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity; 18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len; 18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_identity(sm->eap, &identity_len); 18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity && 18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((identity_len == WSC_ID_ENROLLEE_LEN && 18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(identity, WSC_ID_ENROLLEE, 18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WSC_ID_ENROLLEE_LEN) == 0) || 18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (identity_len == WSC_ID_REGISTRAR_LEN && 18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(identity, WSC_ID_REGISTRAR, 18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WSC_ID_REGISTRAR_LEN) == 0))) { 18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: WLAN_STA_MAYBE_WPS -> " 18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WLAN_STA_WPS"); 18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->flags |= WLAN_STA_WPS; 18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_send(ctx, sta_ctx, type, data, datalen); 19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_aaa_send(void *ctx, void *sta_ctx, 19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t datalen) 19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = ctx; 19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta = sta_ctx; 19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_encapsulate_radius(hapd, sta, data, datalen); 19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void _ieee802_1x_finished(void *ctx, void *sta_ctx, int success, 1916f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int preauth, int remediation) 19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = ctx; 19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta = sta_ctx; 19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (preauth) 19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_finished(hapd, sta, success); 19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1923f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt ieee802_1x_finished(hapd, sta, success, remediation); 19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee802_1x_get_eap_user(void *ctx, const u8 *identity, 19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len, int phase2, 19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_user *user) 19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = ctx; 19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct hostapd_eap_user *eap_user; 19331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int i; 1934912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt int rv = -1; 19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1936d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt eap_user = hostapd_get_eap_user(hapd, identity, identity_len, phase2); 19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_user == NULL) 1938912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt goto out; 19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(user, 0, sizeof(*user)); 19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user->phase2 = phase2; 19421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < EAP_MAX_METHODS; i++) { 19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user->methods[i].vendor = eap_user->methods[i].vendor; 19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user->methods[i].method = eap_user->methods[i].method; 19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_user->password) { 19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user->password = os_malloc(eap_user->password_len); 19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (user->password == NULL) 1950912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt goto out; 19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(user->password, eap_user->password, 19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_user->password_len); 19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user->password_len = eap_user->password_len; 19541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt user->password_hash = eap_user->password_hash; 19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user->force_version = eap_user->force_version; 1957df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt user->macacl = eap_user->macacl; 19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user->ttls_auth = eap_user->ttls_auth; 1959f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt user->remediation = eap_user->remediation; 1960912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt rv = 0; 19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1962912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidtout: 1963912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt if (rv) 1964912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Failed to find user", __func__); 1965912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt 1966912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt return rv; 19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee802_1x_sta_entry_alive(void *ctx, const u8 *addr) 19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = ctx; 19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta; 19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta = ap_get_sta(hapd, addr); 19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta == NULL || sta->eapol_sm == NULL) 19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_logger(void *ctx, const u8 *addr, 19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_logger_level level, const char *txt) 19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_HOSTAPD_LOGGER 19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = ctx; 19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int hlevel; 19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (level) { 19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAPOL_LOGGER_WARNING: 19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hlevel = HOSTAPD_LEVEL_WARNING; 19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAPOL_LOGGER_INFO: 19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hlevel = HOSTAPD_LEVEL_INFO; 19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAPOL_LOGGER_DEBUG: 19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hlevel = HOSTAPD_LEVEL_DEBUG; 19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE8021X, hlevel, "%s", 20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt txt); 20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_HOSTAPD_LOGGER */ 20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_set_port_authorized(void *ctx, void *sta_ctx, 20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int authorized) 20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = ctx; 20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta = sta_ctx; 20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_set_sta_authorized(hapd, sta, authorized); 20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void _ieee802_1x_abort_auth(void *ctx, void *sta_ctx) 20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = ctx; 20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta = sta_ctx; 20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_abort_auth(hapd, sta); 20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void _ieee802_1x_tx_key(void *ctx, void *sta_ctx) 20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = ctx; 20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta = sta_ctx; 20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_tx_key(hapd, sta); 20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_eapol_event(void *ctx, void *sta_ctx, 20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum eapol_event type) 20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* struct hostapd_data *hapd = ctx; */ 20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta = sta_ctx; 20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (type) { 20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAPOL_AUTH_SM_CHANGE: 20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_sm_notify(sta->wpa_sm); 20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAPOL_AUTH_REAUTHENTICATE: 20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL); 20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_ERP 20496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 20506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic struct eap_server_erp_key * 20516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtieee802_1x_erp_get_key(void *ctx, const char *keyname) 20526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 20536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct hostapd_data *hapd = ctx; 20546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct eap_server_erp_key *erp; 20556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 20566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt dl_list_for_each(erp, &hapd->erp_keys, struct eap_server_erp_key, 20576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt list) { 20586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_strcmp(erp->keyname_nai, keyname) == 0) 20596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return erp; 20606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 20616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 20626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 20636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 20646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 20656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 20666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int ieee802_1x_erp_add_key(void *ctx, struct eap_server_erp_key *erp) 20676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 20686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct hostapd_data *hapd = ctx; 20696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 20706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt dl_list_add(&hapd->erp_keys, &erp->list); 20716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 20726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 20736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 20746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_ERP */ 20756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 20766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ieee802_1x_init(struct hostapd_data *hapd) 20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_auth_config conf; 20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_auth_cb cb; 20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt dl_list_init(&hapd->erp_keys); 20846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&conf, 0, sizeof(conf)); 20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.ctx = hapd; 20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_reauth_period = hapd->conf->eap_reauth_period; 20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.wpa = hapd->conf->wpa; 20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.individual_wep_key_len = hapd->conf->individual_wep_key_len; 20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_server = hapd->conf->eap_server; 20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.ssl_ctx = hapd->ssl_ctx; 20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.msg_ctx = hapd->msg_ctx; 20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_sim_db_priv = hapd->eap_sim_db_priv; 20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_req_id_text = hapd->conf->eap_req_id_text; 20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len; 20966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt conf.erp_send_reauth_start = hapd->conf->erp_send_reauth_start; 20976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt conf.erp_domain = hapd->conf->erp_domain; 20986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt conf.erp = hapd->conf->eap_server_erp; 20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.pac_opaque_encr_key = hapd->conf->pac_opaque_encr_key; 21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_fast_a_id = hapd->conf->eap_fast_a_id; 21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_fast_a_id_len = hapd->conf->eap_fast_a_id_len; 21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_fast_a_id_info = hapd->conf->eap_fast_a_id_info; 21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_fast_prov = hapd->conf->eap_fast_prov; 21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.pac_key_lifetime = hapd->conf->pac_key_lifetime; 21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.pac_key_refresh_time = hapd->conf->pac_key_refresh_time; 21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind; 21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.tnc = hapd->conf->tnc; 21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.wps = hapd->wps; 21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.fragment_size = hapd->conf->fragment_size; 21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.pwd_group = hapd->conf->pwd_group; 211187fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen conf.pbc_in_m1 = hapd->conf->pbc_in_m1; 211234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (hapd->conf->server_id) { 211334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt conf.server_id = (const u8 *) hapd->conf->server_id; 211434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt conf.server_id_len = os_strlen(hapd->conf->server_id); 211534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } else { 211634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt conf.server_id = (const u8 *) "hostapd"; 211734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt conf.server_id_len = 7; 211834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&cb, 0, sizeof(cb)); 21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.eapol_send = ieee802_1x_eapol_send; 21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.aaa_send = ieee802_1x_aaa_send; 21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.finished = _ieee802_1x_finished; 21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.get_eap_user = ieee802_1x_get_eap_user; 21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.sta_entry_alive = ieee802_1x_sta_entry_alive; 21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.logger = ieee802_1x_logger; 21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.set_port_authorized = ieee802_1x_set_port_authorized; 21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.abort_auth = _ieee802_1x_abort_auth; 21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.tx_key = _ieee802_1x_tx_key; 21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.eapol_event = ieee802_1x_eapol_event; 21316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_ERP 21326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt cb.erp_get_key = ieee802_1x_erp_get_key; 21336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt cb.erp_add_key = ieee802_1x_erp_add_key; 21346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_ERP */ 21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->eapol_auth = eapol_auth_init(&conf, &cb); 21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->eapol_auth == NULL) 21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((hapd->conf->ieee802_1x || hapd->conf->wpa) && 21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1)) 21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_client_register(hapd->radius, RADIUS_AUTH, 21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_receive_auth, hapd)) 21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->default_wep_key_len) { 21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < 4; i++) 21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_drv_set_key(hapd->conf->iface, hapd, 21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_ALG_NONE, NULL, i, 0, NULL, 0, 21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_rekey(hapd, NULL); 21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->eapol_auth->default_wep_key == NULL) 21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid ieee802_1x_erp_flush(struct hostapd_data *hapd) 21676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 21686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct eap_server_erp_key *erp; 21696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 21706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt while ((erp = dl_list_first(&hapd->erp_keys, struct eap_server_erp_key, 21716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt list)) != NULL) { 21726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt dl_list_del(&erp->list); 21736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bin_clear_free(erp, sizeof(*erp)); 21746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 21756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 21766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 21776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_deinit(struct hostapd_data *hapd) 21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL); 21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->driver != NULL && 21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (hapd->conf->ieee802_1x || hapd->conf->wpa)) 21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0); 21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_auth_deinit(hapd->eapol_auth); 21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->eapol_auth = NULL; 21886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 21896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ieee802_1x_erp_flush(hapd); 21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, 21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len, int ack) 21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee80211_hdr *hdr; 21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char rfc1042_hdr[ETH_ALEN] = 21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; 22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta == NULL) 22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 22031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2) 22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee80211_hdr *) buf; 22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(pos, rfc1042_hdr, sizeof(rfc1042_hdr)) != 0) 22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += sizeof(rfc1042_hdr); 22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (WPA_GET_BE16(pos) != ETH_P_PAE) 22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ieee802_1x_eapol_tx_status(hapd, sta, pos, buf + len - pos, 22161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ack); 22171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 22181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 22191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 22201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta, 22211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *buf, int len, int ack) 22221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 22231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct ieee802_1x_hdr *xhdr = 22241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (const struct ieee802_1x_hdr *) buf; 22251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *pos = buf + sizeof(*xhdr); 22261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct ieee802_1x_eapol_key *key; 22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < (int) sizeof(*xhdr)) 22291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d " 22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "type=%d length=%d - ack=%d", 22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sta->addr), xhdr->version, xhdr->type, 22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be_to_host16(xhdr->length), ack); 22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (xhdr->type != IEEE802_1X_TYPE_EAPOL_KEY) 22361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 22371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 22381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + sizeof(struct wpa_eapol_key) <= buf + len) { 22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *wpa; 22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa = (const struct wpa_eapol_key *) pos; 22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa->type == EAPOL_KEY_TYPE_RSN || 22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa->type == EAPOL_KEY_TYPE_WPA) 22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_eapol_key_tx_status(hapd->wpa_auth, 22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->wpa_sm, ack); 22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* EAPOL EAP-Packet packets are eventually re-sent by either Supplicant 22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * or Authenticator state machines, but EAPOL-Key packets are not 22491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * retransmitted in case of failure. Try to re-send failed EAPOL-Key 22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * packets couple of times because otherwise STA keys become 22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * unsynchronized with AP. */ 22521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!ack && pos + sizeof(*key) <= buf + len) { 22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (struct ieee802_1x_eapol_key *) pos; 22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key " 22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "frame (%scast index=%d)", 22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_index & BIT(7) ? "uni" : "broad", 22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_index & ~BIT(7)); 22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: re-send EAPOL-Key couple of times (with short delay 22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * between them?). If all attempt fail, report error and 22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * deauthenticate STA so that it will get new keys when 22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authenticating again (e.g., after returning in range). 22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Separate limit/transmit state needed both for unicast and 22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * broadcast keys(?) */ 22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: could move unicast key configuration from ieee802_1x_tx_key() 22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to here and change the key only if the EAPOL-Key packet was Acked. 22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len) 22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL || sm->identity == NULL) 22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = sm->identity_len; 22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->identity; 22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len, 22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int idx) 22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL || sm->radius_class.attr == NULL || 22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx >= (int) sm->radius_class.count) 22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = sm->radius_class.attr[idx].len; 22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->radius_class.attr[idx].data; 22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 229604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstruct wpabuf * ieee802_1x_get_radius_cui(struct eapol_state_machine *sm) 229704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 229804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (sm == NULL) 229904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 230004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return sm->radius_cui; 230104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 230204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 230304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len) 23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 230675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen *len = 0; 23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = sm->eap_if->eapKeyDataLen; 23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->eap_if->eapKeyData; 23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, 23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int enabled) 23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->portEnabled = enabled ? TRUE : FALSE; 23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_auth_step(sm); 23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, 23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int valid) 23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->portValid = valid ? TRUE : FALSE; 23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_auth_step(sm); 23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth) 23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pre_auth) 23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->flags |= EAPOL_SM_PREAUTH; 23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->flags &= ~EAPOL_SM_PREAUTH; 23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23461d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtstatic const char * bool_txt(Boolean val) 23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23481d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt return val ? "TRUE" : "FALSE"; 23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen) 23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO */ 23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, 23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf, size_t buflen) 23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len = 0, ret; 23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 2364fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct os_reltime diff; 236596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt const char *name1; 236696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt const char *name2; 23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xPaePortNumber=%d\n" 23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xPaePortProtocolVersion=%d\n" 23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xPaePortCapabilities=1\n" 23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xPaePortInitialize=%d\n" 23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xPaePortReauthenticate=FALSE\n", 23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->aid, 23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAPOL_VERSION, 23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->initialize); 23806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(buflen - len, ret)) 23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* dot1xAuthConfigTable */ 23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthPaeState=%d\n" 23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthBackendAuthState=%d\n" 23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAdminControlledDirections=%d\n" 23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthOperControlledDirections=%d\n" 23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthControlledPortStatus=%d\n" 23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthControlledPortControl=%d\n" 23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthQuietPeriod=%u\n" 23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthServerTimeout=%u\n" 23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthReAuthPeriod=%u\n" 23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthReAuthEnabled=%s\n" 23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthKeyTxEnabled=%s\n", 23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->auth_pae_state + 1, 23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->be_auth_state + 1, 23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->adminControlledDirections, 24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->operControlledDirections, 24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authPortStatus, 24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->portControl, 24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->quietPeriod, 24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->serverTimeout, 24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->reAuthPeriod, 24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bool_txt(sm->reAuthEnabled), 24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bool_txt(sm->keyTxEnabled)); 24086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(buflen - len, ret)) 24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* dot1xAuthStatsTable */ 24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapolFramesRx=%u\n" 24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapolFramesTx=%u\n" 24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapolStartFramesRx=%u\n" 24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapolLogoffFramesRx=%u\n" 24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapolRespIdFramesRx=%u\n" 24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapolRespFramesRx=%u\n" 24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapolReqIdFramesTx=%u\n" 24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapolReqFramesTx=%u\n" 24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthInvalidEapolFramesRx=%u\n" 24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapLengthErrorFramesRx=%u\n" 24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthLastEapolFrameVersion=%u\n" 24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthLastEapolFrameSource=" MACSTR "\n", 24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolFramesRx, 24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolFramesTx, 24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolStartFramesRx, 24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolLogoffFramesRx, 24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolRespIdFramesRx, 24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolRespFramesRx, 24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolReqIdFramesTx, 24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolReqFramesTx, 24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthInvalidEapolFramesRx, 24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapLengthErrorFramesRx, 24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthLastEapolFrameVersion, 24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sm->addr)); 24386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(buflen - len, ret)) 24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* dot1xAuthDiagTable */ 24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEntersConnecting=%u\n" 24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapLogoffsWhileConnecting=%u\n" 24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEntersAuthenticating=%u\n" 24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthSuccessesWhileAuthenticating=%u\n" 24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthTimeoutsWhileAuthenticating=%u\n" 24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthFailWhileAuthenticating=%u\n" 24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthEapStartsWhileAuthenticating=%u\n" 24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthEapLogoffWhileAuthenticating=%u\n" 24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthReauthsWhileAuthenticated=%u\n" 24538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthEapStartsWhileAuthenticated=%u\n" 24548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthEapLogoffWhileAuthenticated=%u\n" 24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthBackendResponses=%u\n" 24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthBackendAccessChallenges=%u\n" 24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthBackendOtherRequestsToSupplicant=%u\n" 24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthBackendAuthSuccesses=%u\n" 24598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthBackendAuthFails=%u\n", 24608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authEntersConnecting, 24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authEapLogoffsWhileConnecting, 24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authEntersAuthenticating, 24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authAuthSuccessesWhileAuthenticating, 24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authAuthTimeoutsWhileAuthenticating, 24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authAuthFailWhileAuthenticating, 24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authAuthEapStartsWhileAuthenticating, 24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authAuthEapLogoffWhileAuthenticating, 24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authAuthReauthsWhileAuthenticated, 24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authAuthEapStartsWhileAuthenticated, 24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authAuthEapLogoffWhileAuthenticated, 24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->backendResponses, 24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->backendAccessChallenges, 24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->backendOtherRequestsToSupplicant, 24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->backendAuthSuccesses, 24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->backendAuthFails); 24766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(buflen - len, ret)) 24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* dot1xAuthSessionStatsTable */ 2481fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_reltime_age(&sta->acct_session_start, &diff); 24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot1xAuthSessionOctetsRx */ 24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot1xAuthSessionOctetsTx */ 24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot1xAuthSessionFramesRx */ 24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot1xAuthSessionFramesTx */ 24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthSessionId=%08X-%08X\n" 24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthSessionAuthenticMethod=%d\n" 24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthSessionTime=%u\n" 24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthSessionTerminateCause=999\n" 24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthSessionUserName=%s\n", 24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->acct_session_id_hi, sta->acct_session_id_lo, 24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (wpa_key_mgmt_wpa_ieee8021x( 24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_sta_key_mgmt(sta->wpa_sm))) ? 24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1 : 2, 2496fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt (unsigned int) diff.sec, 24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity); 24986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(buflen - len, ret)) 24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25022f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (sm->acct_multi_session_id_hi) { 25032f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 25042f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt "authMultiSessionId=%08X+%08X\n", 25052f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt sm->acct_multi_session_id_hi, 25062f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt sm->acct_multi_session_id_lo); 25072f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (os_snprintf_error(buflen - len, ret)) 25082f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt return len; 25092f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt len += ret; 25102f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt } 25112f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 251296be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt name1 = eap_server_get_name(0, sm->eap_type_authsrv); 251396be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt name2 = eap_server_get_name(0, sm->eap_type_supp); 2514fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 2515fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt "last_eap_type_as=%d (%s)\n" 2516fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt "last_eap_type_sta=%d (%s)\n", 25172f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt sm->eap_type_authsrv, name1, 25182f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt sm->eap_type_supp, name2); 25196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(buflen - len, ret)) 2520fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return len; 2521fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt len += ret; 2522fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_finished(struct hostapd_data *hapd, 2528f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt struct sta_info *sta, int success, 2529f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int remediation) 25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key; 25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: get PMKLifetime from WPA parameters */ 25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const int dot11RSNAConfigPMKLifetime = 43200; 25359ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt unsigned int session_timeout; 25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2537f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_HS20 2538f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (remediation && !sta->remediation) { 2539f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->remediation = 1; 2540f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt os_free(sta->remediation_url); 2541f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->remediation_url = 2542f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt os_strdup(hapd->conf->subscr_remediation_url); 2543f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->remediation_method = 1; /* SOAP-XML SPP */ 2544f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2545f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2546f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (success) { 2547f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sta->remediation) { 2548f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification " 2549f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "to " MACSTR " to indicate Subscription " 2550f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "Remediation", 2551f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt MAC2STR(sta->addr)); 2552f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt hs20_send_wnm_notification(hapd, sta->addr, 2553f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->remediation_method, 2554f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->remediation_url); 2555f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt os_free(sta->remediation_url); 2556f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt sta->remediation_url = NULL; 2557f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2558f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 2559f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (sta->hs20_deauth_req) { 2560f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification " 2561f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "to " MACSTR " to indicate imminent " 2562f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt "deauthentication", MAC2STR(sta->addr)); 2563f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt hs20_send_wnm_notification_deauth_req( 2564f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt hapd, sta->addr, sta->hs20_deauth_req); 2565f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2566f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 2567f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_HS20 */ 2568f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = ieee802_1x_get_key(sta->eapol_sm, &len); 25709ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt if (sta->session_timeout_set) 25719ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt session_timeout = sta->session_timeout; 25729ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt else 25739ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt session_timeout = dot11RSNAConfigPMKLifetime; 2574f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (success && key && len >= PMK_LEN && !sta->remediation && 2575f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt !sta->hs20_deauth_requested && 25769ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt wpa_auth_pmksa_add(sta->wpa_sm, key, session_timeout, 25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm) == 0) { 25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, 25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Added PMKSA cache entry (IEEE 802.1X)"); 25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!success) { 25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Many devices require deauthentication after WPS provisioning 25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and some may not be be able to do that themselves, so 25871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * disconnect the client here. In addition, this may also 25881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * benefit IEEE 802.1X/EAPOL authentication cases, too since 25891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * the EAPOL PAE state machine would remain in HELD state for 25901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * considerable amount of time and some EAP methods, like 25911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * EAP-FAST with anonymous provisioning, may require another 25921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * EAPOL authentication to be started to complete connection. 25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 25941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "IEEE 802.1X: Force " 25951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "disconnection after EAP-Failure"); 25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Add a small sleep to increase likelihood of previously 25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * requested EAP-Failure TX getting out before this should the 25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * driver reorder operations. 25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_sleep(0, 10000); 26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_sta_disconnect(hapd, sta, sta->addr, 26021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WLAN_REASON_IEEE_802_1X_AUTH_FAILED); 2603fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt hostapd_wps_eap_completed(hapd); 26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2606