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" 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_1x.h" 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_finished(struct hostapd_data *hapd, 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, int success); 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta, 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 type, const u8 *data, size_t datalen) 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *xhdr; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int encrypt = 0; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = sizeof(*xhdr) + datalen; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(len); 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "malloc() failed for " 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ieee802_1x_send(len=%lu)", 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len); 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xhdr = (struct ieee802_1x_hdr *) buf; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xhdr->version = hapd->conf->eapol_version; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xhdr->type = type; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xhdr->length = host_to_be16(datalen); 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (datalen > 0 && data != NULL) 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(xhdr + 1, data, datalen); 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_pairwise_set(sta->wpa_sm)) 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encrypt = 1; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->flags & WLAN_STA_PREAUTH) { 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_send(hapd, sta, buf, len); 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_drv_hapd_send_eapol(hapd, sta->addr, buf, len, 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encrypt, sta->flags); 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_set_sta_authorized(struct hostapd_data *hapd, 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, int authorized) 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->flags & WLAN_STA_PREAUTH) 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (authorized) { 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_sta_set_authorized(hapd, sta, 1); 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = hostapd_set_authorized(hapd, sta, 1); 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "authorizing port"); 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_sta_set_authorized(hapd, sta, 0); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = hostapd_set_authorized(hapd, sta, 0); 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "unauthorizing port"); 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res && errno != ENOENT) { 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not set station " MACSTR " flags for kernel " 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver (errno=%d).\n", MAC2STR(sta->addr), errno); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (authorized) 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt accounting_sta_start(hapd, sta); 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_tx_key_one(struct hostapd_data *hapd, 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int idx, int broadcast, 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key_data, size_t key_len) 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *ekey; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *hdr; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_eapol_key *key; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, ekey_len; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = sizeof(*key) + key_len; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(sizeof(*hdr) + len); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee802_1x_hdr *) buf; 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (struct ieee802_1x_eapol_key *) (hdr + 1); 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->type = EAPOL_KEY_TYPE_RC4; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_length = htons(key_len); 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_get_ntp_timestamp(key->replay_counter); 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(key->key_iv, sizeof(key->key_iv))) { 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not get random numbers"); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_index = idx | (broadcast ? 0 : BIT(7)); 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->eapol_key_index_workaround) { 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* According to some information, WinXP Supplicant seems to 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * interpret bit7 as an indication whether the key is to be 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * activated, so make it possible to enable workaround that 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * sets this bit for all keys. */ 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_index |= BIT(7); 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Key is encrypted using "Key-IV + MSK[0..31]" as the RC4-key and 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * MSK[32..63] is used to sign the message. */ 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_if->eapKeyData == NULL || sm->eap_if->eapKeyDataLen < 64) { 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "No eapKeyData available for encrypting " 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "and signing EAPOL-Key"); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy((u8 *) (key + 1), key_data, key_len); 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ekey_len = sizeof(key->key_iv) + 32; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ekey = os_malloc(ekey_len); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ekey == NULL) { 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not encrypt key"); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ekey, key->key_iv, sizeof(key->key_iv)); 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ekey + sizeof(key->key_iv), sm->eap_if->eapKeyData, 32); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rc4_skip(ekey, ekey_len, 0, (u8 *) (key + 1), key_len); 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ekey); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* This header is needed here for HMAC-MD5, but it will be regenerated 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * in ieee802_1x_send() */ 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->version = hapd->conf->eapol_version; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->length = host_to_be16(len); 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_md5(sm->eap_if->eapKeyData + 32, 32, buf, sizeof(*hdr) + len, 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_signature); 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Sending EAPOL-Key to " MACSTR 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " (%s index=%d)", MAC2STR(sm->addr), 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt broadcast ? "broadcast" : "unicast", idx); 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_send(hapd, sta, IEEE802_1X_TYPE_EAPOL_KEY, (u8 *) key, len); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->eapol_sm) 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->dot1xAuthEapolFramesTx++; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_VLAN 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct hostapd_wep_keys * 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname) 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_wep_keys *key; 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_zalloc(sizeof(*key)); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->default_len = hapd->conf->default_wep_key_len; 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key->idx >= hapd->conf->broadcast_key_idx_max || 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->idx < hapd->conf->broadcast_key_idx_min) 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->idx = hapd->conf->broadcast_key_idx_min; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->idx++; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!key->key[key->idx]) 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key[key->idx] = os_malloc(key->default_len); 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key->key[key->idx] == NULL || 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt random_get_bytes(key->key[key->idx], key->default_len)) { 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not generate random WEP key (dynamic VLAN).\n"); 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(key->key[key->idx]); 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key[key->idx] = NULL; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(key); 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->len[key->idx] = key->default_len; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Default WEP idx %d for dynamic VLAN\n", 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifname, key->idx); 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "Default WEP key (dynamic VLAN)", 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key[key->idx], key->len[key->idx]); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_WEP, 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt broadcast_ether_addr, key->idx, 1, 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0, key->key[key->idx], 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->len[key->idx])) 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not set dynamic VLAN WEP encryption key.\n"); 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_set_drv_ieee8021x(hapd, ifname, 1); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct hostapd_wep_keys * 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtieee802_1x_get_group(struct hostapd_data *hapd, struct hostapd_ssid *ssid, 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t vlan_id) 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *ifname; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (vlan_id == 0) 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return &ssid->wep; 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (vlan_id <= ssid->max_dyn_vlan_keys && ssid->dyn_vlan_keys && 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid->dyn_vlan_keys[vlan_id]) 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ssid->dyn_vlan_keys[vlan_id]; 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Creating new group " 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "state machine for VLAN ID %lu", 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) vlan_id); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id); 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ifname == NULL) { 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Unknown VLAN ID %lu - " 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "cannot create group key state machine", 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) vlan_id); 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid->dyn_vlan_keys == NULL) { 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int size = (vlan_id + 1) * sizeof(ssid->dyn_vlan_keys[0]); 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid->dyn_vlan_keys = os_zalloc(size); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid->dyn_vlan_keys == NULL) 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid->max_dyn_vlan_keys = vlan_id; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid->max_dyn_vlan_keys < vlan_id) { 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_wep_keys **na; 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int size = (vlan_id + 1) * sizeof(ssid->dyn_vlan_keys[0]); 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt na = os_realloc(ssid->dyn_vlan_keys, size); 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (na == NULL) 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid->dyn_vlan_keys = na; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&ssid->dyn_vlan_keys[ssid->max_dyn_vlan_keys + 1], 0, 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (vlan_id - ssid->max_dyn_vlan_keys) * 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(ssid->dyn_vlan_keys[0])); 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid->max_dyn_vlan_keys = vlan_id; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid->dyn_vlan_keys[vlan_id] = ieee802_1x_group_alloc(hapd, ifname); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ssid->dyn_vlan_keys[vlan_id]; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_VLAN */ 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta) 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_authenticator *eapol = hapd->eapol_auth; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_VLAN 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_wep_keys *key = NULL; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int vlan_id; 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_VLAN */ 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL || !sm->eap_if->eapKeyData) 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Sending EAPOL-Key(s) to " MACSTR, 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sta->addr)); 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_VLAN 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vlan_id = sta->vlan_id; 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (vlan_id < 0 || vlan_id > MAX_VLAN_ID) 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vlan_id = 0; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (vlan_id) { 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = ieee802_1x_get_group(hapd, sta->ssid, vlan_id); 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key && key->key[key->idx]) 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_tx_key_one(hapd, sta, key->idx, 1, 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key[key->idx], 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->len[key->idx]); 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_VLAN */ 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eapol->default_wep_key) { 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_tx_key_one(hapd, sta, eapol->default_wep_key_idx, 1, 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key, 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->default_wep_key_len); 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->individual_wep_key_len > 0) { 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *ikey; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikey = os_malloc(hapd->conf->individual_wep_key_len); 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikey == NULL || 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt random_get_bytes(ikey, hapd->conf->individual_wep_key_len)) 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not generate random " 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "individual WEP key."); 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ikey); 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "Individual WEP key", 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikey, hapd->conf->individual_wep_key_len); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_tx_key_one(hapd, sta, 0, 0, ikey, 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->individual_wep_key_len); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: set encryption in TX callback, i.e., only after STA 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * has ACKed EAPOL-Key frame */ 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->addr, 0, 1, NULL, 0, ikey, 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->individual_wep_key_len)) { 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Could not set individual WEP " 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "encryption."); 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ikey); 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst char *radius_mode_txt(struct hostapd_data *hapd) 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hapd->iface->conf->hw_mode) { 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211A: 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "802.11a"; 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211G: 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "802.11g"; 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211B: 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "802.11b"; 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta) 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rate = 0; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < sta->supported_rates_len; i++) 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((sta->supported_rates[i] & 0x7f) > rate) 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rate = sta->supported_rates[i] & 0x7f; 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return rate; 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_learn_identity(struct hostapd_data *hapd, 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm, 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *eap, size_t len) 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len <= sizeof(struct eap_hdr) || 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap[sizeof(struct eap_hdr)] != EAP_TYPE_IDENTITY) 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_identity(sm->eap, &identity_len); 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity == NULL) 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Save station identity for future RADIUS packets */ 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->identity); 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity = os_malloc(identity_len + 1); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->identity == NULL) { 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len = 0; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->identity, identity, identity_len); 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len = identity_len; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity[identity_len] = '\0'; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X, 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "STA identity '%s'", sm->identity); 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolRespIdFramesRx++; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd, 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *eap, size_t len) 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[128]; 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_learn_identity(hapd, sm, eap, len); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS " 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "packet"); 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->radius_identifier = radius_client_get_id(hapd->radius); 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->radius_identifier); 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) { 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not create net RADIUS packet\n"); 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta)); 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->identity && 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity, sm->identity_len)) { 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not add User-Name\n"); 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->own_ip_addr.af == AF_INET && 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) { 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not add NAS-IP-Address\n"); 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->own_ip_addr.af == AF_INET6 && 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) { 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not add NAS-IPv6-Address\n"); 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->nas_identifier && 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) hapd->conf->nas_identifier, 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(hapd->conf->nas_identifier))) { 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not add NAS-Identifier\n"); 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) { 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not add NAS-Port\n"); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid); 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[sizeof(buf) - 1] = '\0'; 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) buf, os_strlen(buf))) { 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not add Called-Station-Id\n"); 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sta->addr)); 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[sizeof(buf) - 1] = '\0'; 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) buf, os_strlen(buf))) { 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not add Calling-Station-Id\n"); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: should probably check MTU from driver config; 2304 is max for 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE 802.11, but use 1400 to avoid problems with too large packets 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) { 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not add Framed-MTU\n"); 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not add NAS-Port-Type\n"); 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->flags & WLAN_STA_PREAUTH) { 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(buf, "IEEE 802.11i Pre-Authentication", 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(buf)); 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s", 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_sta_rate(hapd, sta) / 2, 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (radius_sta_rate(hapd, sta) & 1) ? ".5" : "", 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_mode_txt(hapd)); 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[sizeof(buf) - 1] = '\0'; 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) buf, os_strlen(buf))) { 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not add Connect-Info\n"); 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap && !radius_msg_add_eap(msg, eap, len)) { 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not add EAP-Message\n"); 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* State attribute must be copied if and only if this packet is 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Access-Request reply to the previous Access-Challenge */ 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->last_recv_radius && 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_get_hdr(sm->last_recv_radius)->code == 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_CODE_ACCESS_CHALLENGE) { 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res = radius_msg_copy_attr(msg, sm->last_recv_radius, 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_ATTR_STATE); 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not copy State attribute from previous " 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Access-Challenge\n"); 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res > 0) { 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Copied RADIUS State Attribute"); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, sta->addr) < 0) 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fail: 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(msg); 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_eap_response(struct hostapd_data *hapd, 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, struct eap_hdr *eap, 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len) 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 type, *data; 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = (u8 *) (eap + 1); 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < sizeof(*eap) + 1) { 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("handle_eap_response: too short response data\n"); 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_type_supp = type = data[0]; 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X, 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d " 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "id=%d len=%d) from STA: EAP Response-%s (%d)", 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->code, eap->identifier, be_to_host16(eap->length), 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_get_name(0, type), type); 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolRespFramesRx++; 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(sm->eap_if->eapRespData); 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len); 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eapolEap = TRUE; 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Process incoming EAP packet from Supplicant */ 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_eap(struct hostapd_data *hapd, struct sta_info *sta, 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, size_t len) 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *eap; 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 eap_len; 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < sizeof(*eap)) { 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf(" too short EAP packet\n"); 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = (struct eap_hdr *) buf; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_len = be_to_host16(eap->length); 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP: code=%d identifier=%d length=%d", 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->code, eap->identifier, eap_len); 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_len < sizeof(*eap)) { 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " Invalid EAP length"); 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (eap_len > len) { 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " Too short frame to contain this EAP " 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "packet"); 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (eap_len < len) { 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " Ignoring %lu extra bytes after EAP " 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "packet", (unsigned long) len - eap_len); 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (eap->code) { 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_REQUEST: 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " (request)"); 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_RESPONSE: 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " (response)"); 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handle_eap_response(hapd, sta, eap, eap_len); 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_SUCCESS: 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " (success)"); 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_FAILURE: 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " (failure)"); 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " (unknown code)"); 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eapol_state_machine * 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta) 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int flags = 0; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->flags & WLAN_STA_PREAUTH) 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= EAPOL_SM_PREAUTH; 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->wpa_sm) { 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= EAPOL_SM_USES_WPA; 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_sta_get_pmksa(sta->wpa_sm)) 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= EAPOL_SM_FROM_PMKSA_CACHE; 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eapol_auth_alloc(hapd->eapol_auth, sta->addr, flags, 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->wps_ie, sta->p2p_ie, sta); 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ieee802_1x_receive - Process the EAPOL frames from the Supplicant 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @hapd: hostapd BSS data 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sa: Source address (sender of the EAPOL frame) 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: EAPOL frame 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of buf in octets 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called for each incoming EAPOL frame from the interface 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len) 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta; 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *hdr; 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_eapol_key *key; 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 datalen; 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *pmksa; 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_mgmt; 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!hapd->conf->ieee802_1x && !hapd->conf->wpa && 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !hapd->conf->wps_state) 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR, 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, MAC2STR(sa)); 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta = ap_get_sta(hapd, sa); 6791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!sta || (!(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH)) && 6801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED))) { 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not " 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "associated/Pre-authenticating STA"); 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < sizeof(*hdr)) { 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf(" too short IEEE 802.1X packet\n"); 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee802_1x_hdr *) buf; 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt datalen = be_to_host16(hdr->length); 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " IEEE 802.1X: version=%d type=%d length=%d", 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->version, hdr->type, datalen); 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len - sizeof(*hdr) < datalen) { 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf(" frame too short for this IEEE 802.1X packet\n"); 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->eapol_sm) 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->dot1xAuthEapLengthErrorFramesRx++; 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len - sizeof(*hdr) > datalen) { 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " ignoring %lu extra octets after " 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IEEE 802.1X packet", 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len - sizeof(*hdr) - datalen); 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->eapol_sm) { 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->dot1xAuthLastEapolFrameVersion = hdr->version; 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->dot1xAuthEapolFramesRx++; 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (struct ieee802_1x_eapol_key *) (hdr + 1); 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (datalen >= sizeof(struct ieee802_1x_eapol_key) && 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->type == IEEE802_1X_TYPE_EAPOL_KEY && 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (key->type == EAPOL_KEY_TYPE_WPA || 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->type == EAPOL_KEY_TYPE_RSN)) { 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_receive(hapd->wpa_auth, sta->wpa_sm, (u8 *) hdr, 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*hdr) + datalen); 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!hapd->conf->ieee802_1x && 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) { 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - " 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "802.1X not enabled and WPS not used"); 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm); 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) { 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - " 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "STA is using PSK"); 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sta->eapol_sm) { 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta); 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sta->eapol_sm) 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 7431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!hapd->conf->ieee802_1x) { 7441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u32 wflags = sta->flags & (WLAN_STA_WPS | 7451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WLAN_STA_WPS2 | 7461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WLAN_STA_MAYBE_WPS); 7471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wflags == WLAN_STA_MAYBE_WPS || 7481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wflags == (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) { 7491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 7501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Delay EAPOL frame transmission until a 7511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * possible WPS STA initiates the handshake 7521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * with EAPOL-Start. Only allow the wait to be 7531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * skipped if the STA is known to support WPS 7541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 2.0. 7551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 7561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Do not start " 7571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "EAPOL until EAPOL-Start is " 7581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "received"); 7591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sta->eapol_sm->flags |= EAPOL_SM_WAIT_START; 7601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->eap_if->portEnabled = TRUE; 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* since we support version 1, we can ignore version field and proceed 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * as specified in version 1 standard [IEEE Std 802.1X-2001, 7.5.5] */ 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: actually, we are not version 1 anymore.. However, Version 2 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * does not change frame contents, so should be ok to process frames 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * more or less identically. Some changes might be needed for 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * verification of fields. */ 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hdr->type) { 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE802_1X_TYPE_EAP_PACKET: 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handle_eap(hapd, sta, (u8 *) (hdr + 1), datalen); 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE802_1X_TYPE_EAPOL_START: 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "received EAPOL-Start " 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from STA"); 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START; 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm); 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa) { 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "cached PMKSA " 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "available - ignore it since " 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "STA sent EAPOL-Start"); 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_sta_clear_pmksa(sta->wpa_sm, pmksa); 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->eapolStart = TRUE; 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->dot1xAuthEapolStartFramesRx++; 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_clear_identity(sta->eapol_sm->eap); 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL); 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE802_1X_TYPE_EAPOL_LOGOFF: 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "received EAPOL-Logoff " 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from STA"); 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->acct_terminate_cause = 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt accounting_sta_stop(hapd, sta); 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->eapolLogoff = TRUE; 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++; 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_clear_identity(sta->eapol_sm->eap); 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE802_1X_TYPE_EAPOL_KEY: 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " EAPOL-Key"); 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ap_sta_is_authorized(sta)) { 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " Dropped key data from " 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unauthorized Supplicant"); 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT: 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " EAPOL-Encapsulated-ASF-Alert"); 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: implement support for this; show data */ 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " unknown IEEE 802.1X packet type"); 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->dot1xAuthInvalidEapolFramesRx++; 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_auth_step(sta->eapol_sm); 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ieee802_1x_new_station - Start IEEE 802.1X authentication 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @hapd: hostapd BSS data 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sta: The station 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to start IEEE 802.1X authentication when a new 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * station completes IEEE 802.11 association. 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *pmksa; 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int reassoc = 1; 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int force_1x = 0; 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_mgmt; 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->wps_state && hapd->conf->wpa && 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) { 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Need to enable IEEE 802.1X/EAPOL state machines for possible 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPS handshake even if IEEE 802.1X/EAPOL is not used for 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication in this BSS. 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt force_1x = 1; 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!force_1x && !hapd->conf->ieee802_1x) { 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - " 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "802.1X not enabled or forced for WPS"); 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm); 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) { 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - using PSK"); 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->eapol_sm == NULL) { 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "start authentication"); 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta); 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->eapol_sm == NULL) { 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_MODULE_IEEE8021X, 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_INFO, 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed to allocate state machine"); 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reassoc = 0; 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START; 8891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS2)) { 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 8911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Delay EAPOL frame transmission until a possible WPS STA 8921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * initiates the handshake with EAPOL-Start. Only allow the 8931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * wait to be skipped if the STA is known to support WPS 2.0. 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Do not start EAPOL until " 8961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "EAPOL-Start is received"); 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->flags |= EAPOL_SM_WAIT_START; 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->eap_if->portEnabled = TRUE; 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->auth_alg == WLAN_AUTH_FT) { 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PMK from FT - skip IEEE 802.1X/EAP"); 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Setup EAPOL state machines to already authenticated state 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * because of existing FT information from R0KH. */ 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->keyRun = TRUE; 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->authSuccess = TRUE; 915c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sta->eapol_sm->authFail = FALSE; 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->eapol_sm->eap) 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_notify_cached(sta->eapol_sm->eap); 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: get vlan_id from R0KH using RRB message */ 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm); 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa) { 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int old_vlanid; 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PMK from PMKSA cache - skip IEEE 802.1X/EAP"); 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Setup EAPOL state machines to already authenticated state 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * because of existing PMKSA information in the cache. */ 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->keyRun = TRUE; 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->authSuccess = TRUE; 937c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sta->eapol_sm->authFail = FALSE; 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->eapol_sm->eap) 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_notify_cached(sta->eapol_sm->eap); 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt old_vlanid = sta->vlan_id; 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_to_eapol_data(pmksa, sta->eapol_sm); 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED) 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->vlan_id = 0; 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_sta_bind_vlan(hapd, sta, old_vlanid); 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reassoc) { 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Force EAPOL state machines to start 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * re-authentication without having to wait for the 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Supplicant to send EAPOL-Start. 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->reAuthenticate = TRUE; 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_auth_step(sta->eapol_sm); 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_free_station(struct sta_info *sta) 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm = NULL; 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(sm->last_recv_radius); 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_free_class(&sm->radius_class); 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->identity); 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_auth_free(sm); 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd, 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta) 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *eap; 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr; 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int eap_type = -1; 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[64]; 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg; 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL || sm->last_recv_radius == NULL) { 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm) 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapNoReq = TRUE; 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = sm->last_recv_radius; 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = radius_msg_get_eap(msg, &len); 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) { 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RFC 3579, Chap. 2.6.3: 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * attribute */ 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_WARNING, "could not extract " 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-Message from RADIUS message"); 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapNoReq = TRUE; 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < sizeof(*hdr)) { 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_WARNING, "too short EAP packet " 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received from authentication server"); 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(eap); 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapNoReq = TRUE; 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > sizeof(*hdr)) 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_type = eap[sizeof(*hdr)]; 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct eap_hdr *) eap; 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hdr->code) { 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_REQUEST: 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_type >= 0) 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_type_authsrv = eap_type; 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)", 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_type >= 0 ? eap_server_get_name(0, eap_type) : 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "??", 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_type); 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_RESPONSE: 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)", 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_type >= 0 ? eap_server_get_name(0, eap_type) : 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "??", 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_type); 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_SUCCESS: 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(buf, "EAP Success", sizeof(buf)); 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_FAILURE: 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(buf, "EAP Failure", sizeof(buf)); 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(buf, "unknown EAP code", sizeof(buf)); 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[sizeof(buf) - 1] = '\0'; 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "decapsulated EAP packet (code=%d " 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "id=%d len=%d) from RADIUS server: %s", 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->code, hdr->identifier, be_to_host16(hdr->length), 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf); 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapReq = TRUE; 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(sm->eap_if->aaaEapReqData); 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapReqData = wpabuf_alloc_ext_data(eap, len); 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_get_keys(struct hostapd_data *hapd, 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, struct radius_msg *msg, 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *req, 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *shared_secret, 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t shared_secret_len) 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_ms_mppe_keys *keys; 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys = radius_msg_get_ms_keys(msg, req, shared_secret, 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt shared_secret_len); 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys && keys->send && keys->recv) { 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len = keys->send_len + keys->recv_len; 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "MS-MPPE-Send-Key", 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->send, keys->send_len); 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "MS-MPPE-Recv-Key", 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->recv, keys->recv_len); 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->eap_if->aaaEapKeyData); 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapKeyData = os_malloc(len); 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_if->aaaEapKeyData) { 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->eap_if->aaaEapKeyData, keys->recv, 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->recv_len); 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->eap_if->aaaEapKeyData + keys->recv_len, 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->send, keys->send_len); 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapKeyDataLen = len; 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapKeyAvailable = TRUE; 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys) { 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->send); 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys->recv); 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(keys); 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_store_radius_class(struct hostapd_data *hapd, 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg) 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *class; 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t class_len; 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int count, i; 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_attr_data *nclass; 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t nclass_count; 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!hapd->conf->radius->acct_server || hapd->radius == NULL || 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm == NULL) 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_free_class(&sm->radius_class); 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = radius_msg_count_attr(msg, RADIUS_ATTR_CLASS, 1); 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (count <= 0) 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nclass = os_zalloc(count * sizeof(struct radius_attr_data)); 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nclass == NULL) 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nclass_count = 0; 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt class = NULL; 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < count; i++) { 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt do { 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CLASS, 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &class, &class_len, 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt class) < 0) { 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i = count; 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } while (class_len < 1); 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nclass[nclass_count].data = os_malloc(class_len); 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nclass[nclass_count].data == NULL) 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(nclass[nclass_count].data, class, class_len); 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nclass[nclass_count].len = class_len; 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nclass_count++; 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->radius_class.attr = nclass; 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->radius_class.count = nclass_count; 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Stored %lu RADIUS Class " 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "attributes for " MACSTR, 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) sm->radius_class.count, 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sta->addr)); 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Update sta->identity based on User-Name attribute in Access-Accept */ 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_update_sta_identity(struct hostapd_data *hapd, 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg) 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *identity; 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, &buf, &len, 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL) < 0) 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = os_malloc(len + 1); 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity == NULL) 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(identity, buf, len); 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity[len] = '\0'; 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "old identity '%s' updated with " 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "User-Name from Access-Accept '%s'", 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity ? (char *) sm->identity : "N/A", 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (char *) identity); 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->identity); 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity = identity; 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len = len; 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct sta_id_search { 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 identifier; 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm; 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee802_1x_select_radius_identifier(struct hostapd_data *hapd, 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx) 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_id_search *id_search = ctx; 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm && sm->radius_identifier >= 0 && 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->radius_identifier == id_search->identifier) { 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id_search->sm = sm; 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eapol_state_machine * 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtieee802_1x_search_radius_identifier(struct hostapd_data *hapd, u8 identifier) 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_id_search id_search; 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id_search.identifier = identifier; 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id_search.sm = NULL; 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_for_each_sta(hapd, ieee802_1x_select_radius_identifier, &id_search); 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return id_search.sm; 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ieee802_1x_receive_auth - Process RADIUS frames from Authentication Server 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg: RADIUS response message 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @req: RADIUS request message 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @shared_secret: RADIUS shared secret 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @shared_secret_len: Length of shared_secret in octets 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Context data (struct hostapd_data *) 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Processing status 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic RadiusRxResult 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *shared_secret, size_t shared_secret_len, 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *data) 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = data; 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta; 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 session_timeout = 0, termination_action, acct_interim_interval; 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int session_timeout_set, old_vlanid = 0; 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm; 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int override_eapReq = 0; 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_hdr *hdr = radius_msg_get_hdr(msg); 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm = ieee802_1x_search_radius_identifier(hapd, hdr->identifier); 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) { 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: Could not find matching " 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "station for this RADIUS message"); 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RADIUS_RX_UNKNOWN; 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta = sm->sta; 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * present when packet contains an EAP-Message attribute */ 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->code == RADIUS_CODE_ACCESS_REJECT && 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL, 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) < 0 && 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) { 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Allowing RADIUS Access-Reject without " 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Message-Authenticator since it does not include " 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-Message"); 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (radius_msg_verify(msg, shared_secret, shared_secret_len, 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req, 1)) { 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Incoming RADIUS packet did not have correct " 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Message-Authenticator - dropped\n"); 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RADIUS_RX_INVALID_AUTHENTICATOR; 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT && 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->code != RADIUS_CODE_ACCESS_REJECT && 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) { 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Unknown RADIUS message code\n"); 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RADIUS_RX_UNKNOWN; 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->radius_identifier = -1; 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RADIUS packet matching with station " MACSTR, 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sta->addr)); 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(sm->last_recv_radius); 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->last_recv_radius = msg; 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt session_timeout_set = 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &session_timeout); 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_TERMINATION_ACTION, 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &termination_action)) 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt termination_action = RADIUS_TERMINATION_ACTION_DEFAULT; 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->acct_interim_interval == 0 && 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->code == RADIUS_CODE_ACCESS_ACCEPT && 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL, 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &acct_interim_interval) == 0) { 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (acct_interim_interval < 60) { 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_MODULE_IEEE8021X, 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_INFO, 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ignored too small " 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Acct-Interim-Interval %d", 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt acct_interim_interval); 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->acct_interim_interval = acct_interim_interval; 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hdr->code) { 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_CODE_ACCESS_ACCEPT: 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED) 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->vlan_id = 0; 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_VLAN 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt old_vlanid = sta->vlan_id; 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->vlan_id = radius_msg_get_vlanid(msg); 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->vlan_id > 0 && 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_get_vlan_id_ifname(hapd->conf->vlan, 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->vlan_id)) { 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_MODULE_RADIUS, 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_INFO, 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "VLAN ID %d", sta->vlan_id); 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_REQUIRED) { 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->authFail = TRUE; 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_MODULE_IEEE8021X, 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_INFO, "authentication " 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "server did not include required VLAN " 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ID in Access-Accept"); 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_VLAN */ 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ap_sta_bind_vlan(hapd, sta, old_vlanid) < 0) 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RFC 3580, Ch. 3.17 */ 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (session_timeout_set && termination_action == 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_TERMINATION_ACTION_RADIUS_REQUEST) { 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->reAuthPeriod = session_timeout; 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (session_timeout_set) 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_sta_session_timeout(hapd, sta, session_timeout); 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaSuccess = TRUE; 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt override_eapReq = 1; 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_get_keys(hapd, sta, msg, req, shared_secret, 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt shared_secret_len); 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_store_radius_class(hapd, sta, msg); 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_update_sta_identity(hapd, sta, msg); 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_if->eapKeyAvailable && 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_pmksa_add(sta->wpa_sm, sm->eapol_key_crypt, 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt session_timeout_set ? 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) session_timeout : -1, sm) == 0) { 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, 13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Added PMKSA cache entry"); 13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_CODE_ACCESS_REJECT: 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaFail = TRUE; 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt override_eapReq = 1; 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_CODE_ACCESS_CHALLENGE: 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapReq = TRUE; 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (session_timeout_set) { 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RFC 2869, Ch. 2.3.2; RFC 3580, Ch. 3.17 */ 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaMethodTimeout = session_timeout; 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sm->addr, 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_MODULE_IEEE8021X, 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "using EAP timeout of %d seconds (from " 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RADIUS)", 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaMethodTimeout); 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Use dynamic retransmission behavior per EAP 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * specification. 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaMethodTimeout = 0; 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_decapsulate_radius(hapd, sta); 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (override_eapReq) 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->aaaEapReq = FALSE; 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_auth_step(sm); 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RADIUS_RX_QUEUED; 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta) 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "aborting authentication"); 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(sm->last_recv_radius); 14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->last_recv_radius = NULL; 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_if->eapTimeout) { 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Disconnect the STA since it did not reply to the last EAP 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * request and we cannot continue EAP processing (EAP-Failure 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * could only be sent if the EAP peer actually replied). 14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 14161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "EAP Timeout, STA " MACSTR, 14171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(sta->addr)); 14181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->portEnabled = FALSE; 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_sta_disconnect(hapd, sta, sta->addr, 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_REASON_PREV_AUTH_NOT_VALID); 14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd) 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_authenticator *eapol = hapd->eapol_auth; 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->default_wep_key_len < 1) 14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(eapol->default_wep_key); 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key = os_malloc(hapd->conf->default_wep_key_len); 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eapol->default_wep_key == NULL || 14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt random_get_bytes(eapol->default_wep_key, 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->default_wep_key_len)) { 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not generate random WEP key.\n"); 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(eapol->default_wep_key); 14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key = NULL; 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IEEE 802.1X: New default WEP key", 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key, 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->default_wep_key_len); 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee802_1x_sta_key_available(struct hostapd_data *hapd, 14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, void *ctx) 14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta->eapol_sm) { 14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; 14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_auth_step(sta->eapol_sm); 14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx) 14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = eloop_ctx; 14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_authenticator *eapol = hapd->eapol_auth; 14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eapol->default_wep_key_idx >= 3) 14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key_idx = 14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->individual_wep_key_len > 0 ? 1 : 0; 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key_idx++; 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: New default WEP key index %d", 14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key_idx); 14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ieee802_1x_rekey_broadcast(hapd)) { 14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X, 14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_WARNING, "failed to generate a " 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "new broadcast key"); 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(eapol->default_wep_key); 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key = NULL; 14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: Could setup key for RX here, but change default TX keyid only 14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * after new broadcast key has been sent to all stations. */ 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, 14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt broadcast_ether_addr, 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key_idx, 1, NULL, 0, 14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key, 14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->default_wep_key_len)) { 14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X, 14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_WARNING, "failed to configure a " 14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "new broadcast key"); 14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(eapol->default_wep_key); 14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol->default_wep_key = NULL; 14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_for_each_sta(hapd, ieee802_1x_sta_key_available, NULL); 15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->wep_rekeying_period > 0) { 15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(hapd->conf->wep_rekeying_period, 0, 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_rekey, hapd, NULL); 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type, 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t datalen) 15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta = sta_ctx; 15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) == 15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_STA_MAYBE_WPS) { 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity; 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len; 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_identity(sm->eap, &identity_len); 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity && 15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((identity_len == WSC_ID_ENROLLEE_LEN && 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(identity, WSC_ID_ENROLLEE, 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WSC_ID_ENROLLEE_LEN) == 0) || 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (identity_len == WSC_ID_REGISTRAR_LEN && 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(identity, WSC_ID_REGISTRAR, 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WSC_ID_REGISTRAR_LEN) == 0))) { 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: WLAN_STA_MAYBE_WPS -> " 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WLAN_STA_WPS"); 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->flags |= WLAN_STA_WPS; 15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_send(ctx, sta_ctx, type, data, datalen); 15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_aaa_send(void *ctx, void *sta_ctx, 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t datalen) 15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = ctx; 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta = sta_ctx; 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_encapsulate_radius(hapd, sta, data, datalen); 15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void _ieee802_1x_finished(void *ctx, void *sta_ctx, int success, 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int preauth) 15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = ctx; 15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta = sta_ctx; 15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (preauth) 15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_finished(hapd, sta, success); 15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_finished(hapd, sta, success); 15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee802_1x_get_eap_user(void *ctx, const u8 *identity, 15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len, int phase2, 15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_user *user) 15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = ctx; 15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct hostapd_eap_user *eap_user; 15711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int i; 15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_user = hostapd_get_eap_user(hapd->conf, identity, 15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len, phase2); 15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_user == NULL) 15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(user, 0, sizeof(*user)); 15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user->phase2 = phase2; 15801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (i = 0; i < EAP_MAX_METHODS; i++) { 15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user->methods[i].vendor = eap_user->methods[i].vendor; 15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user->methods[i].method = eap_user->methods[i].method; 15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_user->password) { 15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user->password = os_malloc(eap_user->password_len); 15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (user->password == NULL) 15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(user->password, eap_user->password, 15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_user->password_len); 15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user->password_len = eap_user->password_len; 15921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt user->password_hash = eap_user->password_hash; 15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user->force_version = eap_user->force_version; 15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user->ttls_auth = eap_user->ttls_auth; 15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee802_1x_sta_entry_alive(void *ctx, const u8 *addr) 16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = ctx; 16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta; 16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta = ap_get_sta(hapd, addr); 16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta == NULL || sta->eapol_sm == NULL) 16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_logger(void *ctx, const u8 *addr, 16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_logger_level level, const char *txt) 16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_HOSTAPD_LOGGER 16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = ctx; 16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int hlevel; 16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (level) { 16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAPOL_LOGGER_WARNING: 16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hlevel = HOSTAPD_LEVEL_WARNING; 16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAPOL_LOGGER_INFO: 16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hlevel = HOSTAPD_LEVEL_INFO; 16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAPOL_LOGGER_DEBUG: 16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hlevel = HOSTAPD_LEVEL_DEBUG; 16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE8021X, hlevel, "%s", 16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt txt); 16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_HOSTAPD_LOGGER */ 16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_set_port_authorized(void *ctx, void *sta_ctx, 16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int authorized) 16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = ctx; 16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta = sta_ctx; 16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_set_sta_authorized(hapd, sta, authorized); 16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void _ieee802_1x_abort_auth(void *ctx, void *sta_ctx) 16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = ctx; 16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta = sta_ctx; 16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_abort_auth(hapd, sta); 16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void _ieee802_1x_tx_key(void *ctx, void *sta_ctx) 16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = ctx; 16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta = sta_ctx; 16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_tx_key(hapd, sta); 16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_eapol_event(void *ctx, void *sta_ctx, 16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum eapol_event type) 16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* struct hostapd_data *hapd = ctx; */ 16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta = sta_ctx; 16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (type) { 16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAPOL_AUTH_SM_CHANGE: 16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_sm_notify(sta->wpa_sm); 16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAPOL_AUTH_REAUTHENTICATE: 16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL); 16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ieee802_1x_init(struct hostapd_data *hapd) 16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_auth_config conf; 16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_auth_cb cb; 16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&conf, 0, sizeof(conf)); 16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.ctx = hapd; 16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_reauth_period = hapd->conf->eap_reauth_period; 16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.wpa = hapd->conf->wpa; 16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.individual_wep_key_len = hapd->conf->individual_wep_key_len; 16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_server = hapd->conf->eap_server; 16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.ssl_ctx = hapd->ssl_ctx; 16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.msg_ctx = hapd->msg_ctx; 16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_sim_db_priv = hapd->eap_sim_db_priv; 16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_req_id_text = hapd->conf->eap_req_id_text; 16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len; 16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.pac_opaque_encr_key = hapd->conf->pac_opaque_encr_key; 16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_fast_a_id = hapd->conf->eap_fast_a_id; 16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_fast_a_id_len = hapd->conf->eap_fast_a_id_len; 16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_fast_a_id_info = hapd->conf->eap_fast_a_id_info; 17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_fast_prov = hapd->conf->eap_fast_prov; 17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.pac_key_lifetime = hapd->conf->pac_key_lifetime; 17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.pac_key_refresh_time = hapd->conf->pac_key_refresh_time; 17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind; 17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.tnc = hapd->conf->tnc; 17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.wps = hapd->wps; 17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.fragment_size = hapd->conf->fragment_size; 17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.pwd_group = hapd->conf->pwd_group; 170887fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen conf.pbc_in_m1 = hapd->conf->pbc_in_m1; 17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&cb, 0, sizeof(cb)); 17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.eapol_send = ieee802_1x_eapol_send; 17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.aaa_send = ieee802_1x_aaa_send; 17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.finished = _ieee802_1x_finished; 17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.get_eap_user = ieee802_1x_get_eap_user; 17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.sta_entry_alive = ieee802_1x_sta_entry_alive; 17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.logger = ieee802_1x_logger; 17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.set_port_authorized = ieee802_1x_set_port_authorized; 17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.abort_auth = _ieee802_1x_abort_auth; 17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.tx_key = _ieee802_1x_tx_key; 17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.eapol_event = ieee802_1x_eapol_event; 17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->eapol_auth = eapol_auth_init(&conf, &cb); 17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->eapol_auth == NULL) 17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((hapd->conf->ieee802_1x || hapd->conf->wpa) && 17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1)) 17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_client_register(hapd->radius, RADIUS_AUTH, 17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_receive_auth, hapd)) 17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->default_wep_key_len) { 17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < 4; i++) 17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_drv_set_key(hapd->conf->iface, hapd, 17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_ALG_NONE, NULL, i, 0, NULL, 0, 17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_1x_rekey(hapd, NULL); 17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->eapol_auth->default_wep_key == NULL) 17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_deinit(struct hostapd_data *hapd) 17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL); 17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->driver != NULL && 17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (hapd->conf->ieee802_1x || hapd->conf->wpa)) 17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0); 17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_auth_deinit(hapd->eapol_auth); 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->eapol_auth = NULL; 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, 17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len, int ack) 17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee80211_hdr *hdr; 17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char rfc1042_hdr[ETH_ALEN] = 17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; 17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sta == NULL) 17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2) 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee80211_hdr *) buf; 17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(pos, rfc1042_hdr, sizeof(rfc1042_hdr)) != 0) 17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += sizeof(rfc1042_hdr); 17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (WPA_GET_BE16(pos) != ETH_P_PAE) 17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ieee802_1x_eapol_tx_status(hapd, sta, pos, buf + len - pos, 17881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ack); 17891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 17901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta, 17931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *buf, int len, int ack) 17941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 17951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct ieee802_1x_hdr *xhdr = 17961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (const struct ieee802_1x_hdr *) buf; 17971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *pos = buf + sizeof(*xhdr); 17981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct ieee802_1x_eapol_key *key; 17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < (int) sizeof(*xhdr)) 18011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d " 18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "type=%d length=%d - ack=%d", 18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sta->addr), xhdr->version, xhdr->type, 18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be_to_host16(xhdr->length), ack); 18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (xhdr->type != IEEE802_1X_TYPE_EAPOL_KEY) 18081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 18091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 18101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos + sizeof(struct wpa_eapol_key) <= buf + len) { 18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *wpa; 18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa = (const struct wpa_eapol_key *) pos; 18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa->type == EAPOL_KEY_TYPE_RSN || 18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa->type == EAPOL_KEY_TYPE_WPA) 18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_eapol_key_tx_status(hapd->wpa_auth, 18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->wpa_sm, ack); 18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* EAPOL EAP-Packet packets are eventually re-sent by either Supplicant 18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * or Authenticator state machines, but EAPOL-Key packets are not 18211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * retransmitted in case of failure. Try to re-send failed EAPOL-Key 18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * packets couple of times because otherwise STA keys become 18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * unsynchronized with AP. */ 18241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!ack && pos + sizeof(*key) <= buf + len) { 18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (struct ieee802_1x_eapol_key *) pos; 18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, 18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key " 18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "frame (%scast index=%d)", 18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_index & BIT(7) ? "uni" : "broad", 18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key->key_index & ~BIT(7)); 18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: re-send EAPOL-Key couple of times (with short delay 18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * between them?). If all attempt fail, report error and 18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * deauthenticate STA so that it will get new keys when 18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authenticating again (e.g., after returning in range). 18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Separate limit/transmit state needed both for unicast and 18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * broadcast keys(?) */ 18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: could move unicast key configuration from ieee802_1x_tx_key() 18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to here and change the key only if the EAPOL-Key packet was Acked. 18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len) 18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL || sm->identity == NULL) 18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = sm->identity_len; 18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->identity; 18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len, 18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int idx) 18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL || sm->radius_class.attr == NULL || 18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx >= (int) sm->radius_class.count) 18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = sm->radius_class.attr[idx].len; 18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->radius_class.attr[idx].data; 18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len) 18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 187075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen *len = 0; 18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = sm->eap_if->eapKeyDataLen; 18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->eap_if->eapKeyData; 18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, 18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int enabled) 18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_if->portEnabled = enabled ? TRUE : FALSE; 18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_auth_step(sm); 18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, 18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int valid) 18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->portValid = valid ? TRUE : FALSE; 18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_auth_step(sm); 18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth) 19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pre_auth) 19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->flags |= EAPOL_SM_PREAUTH; 19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->flags &= ~EAPOL_SM_PREAUTH; 19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * bool_txt(Boolean bool) 19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return bool ? "TRUE" : "FALSE"; 19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen) 19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO */ 19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, 19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf, size_t buflen) 19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len = 0, ret; 19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_state_machine *sm = sta->eapol_sm; 19281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct os_time t; 19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xPaePortNumber=%d\n" 19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xPaePortProtocolVersion=%d\n" 19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xPaePortCapabilities=1\n" 19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xPaePortInitialize=%d\n" 19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xPaePortReauthenticate=FALSE\n", 19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->aid, 19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAPOL_VERSION, 19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->initialize); 19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* dot1xAuthConfigTable */ 19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthPaeState=%d\n" 19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthBackendAuthState=%d\n" 19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAdminControlledDirections=%d\n" 19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthOperControlledDirections=%d\n" 19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthControlledPortStatus=%d\n" 19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthControlledPortControl=%d\n" 19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthQuietPeriod=%u\n" 19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthServerTimeout=%u\n" 19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthReAuthPeriod=%u\n" 19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthReAuthEnabled=%s\n" 19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthKeyTxEnabled=%s\n", 19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->auth_pae_state + 1, 19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->be_auth_state + 1, 19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->adminControlledDirections, 19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->operControlledDirections, 19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authPortStatus, 19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->portControl, 19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->quietPeriod, 19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->serverTimeout, 19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->reAuthPeriod, 19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bool_txt(sm->reAuthEnabled), 19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bool_txt(sm->keyTxEnabled)); 19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* dot1xAuthStatsTable */ 19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapolFramesRx=%u\n" 19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapolFramesTx=%u\n" 19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapolStartFramesRx=%u\n" 19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapolLogoffFramesRx=%u\n" 19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapolRespIdFramesRx=%u\n" 19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapolRespFramesRx=%u\n" 19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapolReqIdFramesTx=%u\n" 19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapolReqFramesTx=%u\n" 19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthInvalidEapolFramesRx=%u\n" 19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapLengthErrorFramesRx=%u\n" 19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthLastEapolFrameVersion=%u\n" 19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthLastEapolFrameSource=" MACSTR "\n", 19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolFramesRx, 19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolFramesTx, 19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolStartFramesRx, 19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolLogoffFramesRx, 19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolRespIdFramesRx, 19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolRespFramesRx, 19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolReqIdFramesTx, 19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapolReqFramesTx, 19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthInvalidEapolFramesRx, 19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthEapLengthErrorFramesRx, 19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->dot1xAuthLastEapolFrameVersion, 19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(sm->addr)); 20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* dot1xAuthDiagTable */ 20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEntersConnecting=%u\n" 20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEapLogoffsWhileConnecting=%u\n" 20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthEntersAuthenticating=%u\n" 20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthSuccessesWhileAuthenticating=%u\n" 20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthTimeoutsWhileAuthenticating=%u\n" 20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthFailWhileAuthenticating=%u\n" 20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthEapStartsWhileAuthenticating=%u\n" 20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthEapLogoffWhileAuthenticating=%u\n" 20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthReauthsWhileAuthenticated=%u\n" 20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthEapStartsWhileAuthenticated=%u\n" 20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthAuthEapLogoffWhileAuthenticated=%u\n" 20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthBackendResponses=%u\n" 20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthBackendAccessChallenges=%u\n" 20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthBackendOtherRequestsToSupplicant=%u\n" 20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthBackendAuthSuccesses=%u\n" 20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthBackendAuthFails=%u\n", 20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authEntersConnecting, 20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authEapLogoffsWhileConnecting, 20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authEntersAuthenticating, 20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authAuthSuccessesWhileAuthenticating, 20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authAuthTimeoutsWhileAuthenticating, 20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authAuthFailWhileAuthenticating, 20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authAuthEapStartsWhileAuthenticating, 20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authAuthEapLogoffWhileAuthenticating, 20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authAuthReauthsWhileAuthenticated, 20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authAuthEapStartsWhileAuthenticated, 20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->authAuthEapLogoffWhileAuthenticated, 20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->backendResponses, 20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->backendAccessChallenges, 20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->backendOtherRequestsToSupplicant, 20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->backendAuthSuccesses, 20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->backendAuthFails); 20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* dot1xAuthSessionStatsTable */ 20431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_get_time(&t); 20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot1xAuthSessionOctetsRx */ 20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot1xAuthSessionOctetsTx */ 20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot1xAuthSessionFramesRx */ 20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: dot1xAuthSessionFramesTx */ 20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthSessionId=%08X-%08X\n" 20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthSessionAuthenticMethod=%d\n" 20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthSessionTime=%u\n" 20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthSessionTerminateCause=999\n" 20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dot1xAuthSessionUserName=%s\n", 20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->acct_session_id_hi, sta->acct_session_id_lo, 20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (wpa_key_mgmt_wpa_ieee8021x( 20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_sta_key_mgmt(sta->wpa_sm))) ? 20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1 : 2, 20581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (unsigned int) (t.sec - sta->acct_session_start), 20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity); 20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_finished(struct hostapd_data *hapd, 20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta, int success) 20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key; 20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: get PMKLifetime from WPA parameters */ 20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static const int dot11RSNAConfigPMKLifetime = 43200; 20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = ieee802_1x_get_key(sta->eapol_sm, &len); 20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (success && key && len >= PMK_LEN && 20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_pmksa_add(sta->wpa_sm, key, dot11RSNAConfigPMKLifetime, 20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta->eapol_sm) == 0) { 20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, 20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Added PMKSA cache entry (IEEE 802.1X)"); 20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!success) { 20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Many devices require deauthentication after WPS provisioning 20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and some may not be be able to do that themselves, so 20891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * disconnect the client here. In addition, this may also 20901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * benefit IEEE 802.1X/EAPOL authentication cases, too since 20911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * the EAPOL PAE state machine would remain in HELD state for 20921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * considerable amount of time and some EAP methods, like 20931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * EAP-FAST with anonymous provisioning, may require another 20941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * EAPOL authentication to be started to complete connection. 20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 20961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "IEEE 802.1X: Force " 20971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "disconnection after EAP-Failure"); 20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Add a small sleep to increase likelihood of previously 20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * requested EAP-Failure TX getting out before this should the 21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * driver reorder operations. 21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_sleep(0, 10000); 21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_sta_disconnect(hapd, sta, sta->addr, 21041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WLAN_REASON_IEEE_802_1X_AUTH_FAILED); 21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2107