wpa_auth_glue.c revision c5ec7f57ead87efa365800228aa0b09a12d9e6c4
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * hostapd / WPA authenticator glue code 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi> 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This software may be distributed under the terms of the BSD license. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See README for more details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "utils/includes.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "utils/common.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "common/ieee802_11_defs.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "eapol_auth/eapol_auth_sm.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "eapol_auth/eapol_auth_sm_i.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "eap_server/eap.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "l2_packet/l2_packet.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "drivers/driver.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hostapd.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ieee802_1x.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "preauth_auth.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sta_info.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tkip_countermeasures.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ap_drv_ops.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ap_config.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "wpa_auth.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "wpa_auth_glue.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct wpa_auth_config *wconf) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_memset(wconf, 0, sizeof(*wconf)); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->wpa = conf->wpa; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->wpa_key_mgmt = conf->wpa_key_mgmt; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->wpa_pairwise = conf->wpa_pairwise; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->wpa_group = conf->wpa_group; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->wpa_group_rekey = conf->wpa_group_rekey; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->wpa_strict_rekey = conf->wpa_strict_rekey; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->rsn_pairwise = conf->rsn_pairwise; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->rsn_preauth = conf->rsn_preauth; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->eapol_version = conf->eapol_version; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->peerkey = conf->peerkey; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->wmm_enabled = conf->wmm_enabled; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->wmm_uapsd = conf->wmm_uapsd; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->disable_pmksa_caching = conf->disable_pmksa_caching; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->okc = conf->okc; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef CONFIG_IEEE80211W 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->ieee80211w = conf->ieee80211w; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* CONFIG_IEEE80211W */ 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef CONFIG_IEEE80211R 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->ssid_len = conf->ssid.ssid_len; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (wconf->ssid_len > SSID_LEN) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->ssid_len = SSID_LEN; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_memcpy(wconf->mobility_domain, conf->mobility_domain, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MOBILITY_DOMAIN_ID_LEN); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (conf->nas_identifier && 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_strlen(conf->nas_identifier) <= FT_R0KH_ID_MAX_LEN) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->r0_key_holder_len = os_strlen(conf->nas_identifier); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_memcpy(wconf->r0_key_holder, conf->nas_identifier, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->r0_key_holder_len); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_memcpy(wconf->r1_key_holder, conf->r1_key_holder, FT_R1KH_ID_LEN); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->r0_key_lifetime = conf->r0_key_lifetime; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->reassociation_deadline = conf->reassociation_deadline; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->r0kh_list = conf->r0kh_list; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->r1kh_list = conf->r1kh_list; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->pmk_r1_push = conf->pmk_r1_push; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wconf->ft_over_ds = conf->ft_over_ds; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* CONFIG_IEEE80211R */ 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void hostapd_wpa_auth_logger(void *ctx, const u8 *addr, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logger_level level, const char *txt) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CONFIG_NO_HOSTAPD_LOGGER 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd = ctx; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int hlevel; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (level) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LOGGER_WARNING: 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hlevel = HOSTAPD_LEVEL_WARNING; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LOGGER_INFO: 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hlevel = HOSTAPD_LEVEL_INFO; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LOGGER_DEBUG: 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hlevel = HOSTAPD_LEVEL_DEBUG; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hostapd_logger(hapd, addr, HOSTAPD_MODULE_WPA, hlevel, "%s", txt); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* CONFIG_NO_HOSTAPD_LOGGER */ 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 reason) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd = ctx; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wpa_printf(MSG_DEBUG, "%s: WPA authenticator requests disconnect: " 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "STA " MACSTR " reason %d", 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, MAC2STR(addr), reason); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ap_sta_disconnect(hapd, NULL, addr, reason); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd = ctx; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) michael_mic_failure(hapd, addr, 0); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr, 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wpa_eapol_variable var, int value) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd = ctx; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sta_info *sta = ap_get_sta(hapd, addr); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sta == NULL) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (var) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WPA_EAPOL_portEnabled: 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ieee802_1x_notify_port_enabled(sta->eapol_sm, value); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WPA_EAPOL_portValid: 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ieee802_1x_notify_port_valid(sta->eapol_sm, value); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WPA_EAPOL_authorized: 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ieee802_1x_set_sta_authorized(hapd, sta, value); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WPA_EAPOL_portControl_Auto: 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sta->eapol_sm) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sta->eapol_sm->portControl = Auto; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WPA_EAPOL_keyRun: 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sta->eapol_sm) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sta->eapol_sm->keyRun = value ? TRUE : FALSE; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WPA_EAPOL_keyAvailable: 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sta->eapol_sm) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sta->eapol_sm->eap_if->eapKeyAvailable = 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value ? TRUE : FALSE; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WPA_EAPOL_keyDone: 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sta->eapol_sm) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sta->eapol_sm->keyDone = value ? TRUE : FALSE; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WPA_EAPOL_inc_EapolFramesTx: 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sta->eapol_sm) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sta->eapol_sm->dot1xAuthEapolFramesTx++; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wpa_eapol_variable var) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd = ctx; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sta_info *sta = ap_get_sta(hapd, addr); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sta == NULL || sta->eapol_sm == NULL) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (var) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WPA_EAPOL_keyRun: 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sta->eapol_sm->keyRun; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WPA_EAPOL_keyAvailable: 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sta->eapol_sm->eap_if->eapKeyAvailable; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const u8 *prev_psk) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd = ctx; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sta_info *sta = ap_get_sta(hapd, addr); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sta && sta->psk) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sta->psk; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hostapd_get_psk(hapd->conf, addr, prev_psk); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int hostapd_wpa_auth_get_msk(void *ctx, const u8 *addr, u8 *msk, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t *len) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd = ctx; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const u8 *key; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t keylen; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sta_info *sta; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sta = ap_get_sta(hapd, addr); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sta == NULL) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = ieee802_1x_get_key(sta->eapol_sm, &keylen); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key == NULL) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (keylen > *len) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keylen = *len; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_memcpy(msk, key, keylen); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *len = keylen; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const u8 *addr, int idx, u8 *key, 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t key_len) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd = ctx; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *ifname = hapd->conf->iface; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (vlan_id > 0) { 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ifname == NULL) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0, 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key, key_len); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int hostapd_wpa_auth_get_seqnum(void *ctx, const u8 *addr, int idx, 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u8 *seq) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd = ctx; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hostapd_get_seqnum(hapd->conf->iface, hapd, addr, idx, seq); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr, 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const u8 *data, size_t data_len, 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int encrypt) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd = ctx; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sta_info *sta; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u32 flags = 0; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sta = ap_get_sta(hapd, addr); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sta) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags = hostapd_sta_flags_to_drv(sta->flags); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hostapd_drv_hapd_send_eapol(hapd, addr, data, data_len, 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encrypt, flags); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int hostapd_wpa_auth_for_each_sta( 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *ctx, int (*cb)(struct wpa_state_machine *sm, void *ctx), 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *cb_ctx) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd = ctx; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sta_info *sta; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (sta = hapd->sta_list; sta; sta = sta->next) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx)) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct wpa_auth_iface_iter_data { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int (*cb)(struct wpa_authenticator *sm, void *ctx); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *cb_ctx; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int wpa_auth_iface_iter(struct hostapd_iface *iface, void *ctx) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct wpa_auth_iface_iter_data *data = ctx; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t i; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < iface->num_bss; i++) { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iface->bss[i]->wpa_auth && 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->cb(iface->bss[i]->wpa_auth, data->cb_ctx)) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int hostapd_wpa_auth_for_each_auth( 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *ctx, int (*cb)(struct wpa_authenticator *sm, void *ctx), 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *cb_ctx) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd = ctx; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct wpa_auth_iface_iter_data data; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hapd->iface->for_each_interface == NULL) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.cb = cb; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.cb_ctx = cb_ctx; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hapd->iface->for_each_interface(hapd->iface->interfaces, 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wpa_auth_iface_iter, &data); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef CONFIG_IEEE80211R 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct wpa_auth_ft_iface_iter_data { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *src_hapd; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const u8 *dst; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const u8 *data; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t data_len; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct wpa_auth_ft_iface_iter_data *idata = ctx; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t j; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (j = 0; j < iface->num_bss; j++) { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hapd = iface->bss[j]; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hapd == idata->src_hapd) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (os_memcmp(hapd->own_addr, idata->dst, ETH_ALEN) == 0) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wpa_printf(MSG_DEBUG, "FT: Send RRB data directly to " 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "locally managed BSS " MACSTR "@%s -> " 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MACSTR "@%s", 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAC2STR(idata->src_hapd->own_addr), 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) idata->src_hapd->conf->iface, 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAC2STR(hapd->own_addr), hapd->conf->iface); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wpa_ft_rrb_rx(hapd->wpa_auth, 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) idata->src_hapd->own_addr, 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) idata->data, idata->data_len); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* CONFIG_IEEE80211R */ 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto, 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const u8 *data, size_t data_len) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd = ctx; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct l2_ethhdr *buf; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ret; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef CONFIG_IEEE80211R 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (proto == ETH_P_RRB && hapd->iface->for_each_interface) { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int res; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct wpa_auth_ft_iface_iter_data idata; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) idata.src_hapd = hapd; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) idata.dst = dst; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) idata.data = data; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) idata.data_len = data_len; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = hapd->iface->for_each_interface(hapd->iface->interfaces, 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hostapd_wpa_auth_ft_iter, 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &idata); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (res == 1) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return data_len; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* CONFIG_IEEE80211R */ 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hapd->driver && hapd->driver->send_ether) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hapd->driver->send_ether(hapd->drv_priv, dst, 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hapd->own_addr, proto, 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data, data_len); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hapd->l2 == NULL) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf = os_malloc(sizeof(*buf) + data_len); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buf == NULL) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_memcpy(buf->h_dest, dst, ETH_ALEN); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_memcpy(buf->h_source, hapd->own_addr, ETH_ALEN); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf->h_proto = host_to_be16(proto); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_memcpy(buf + 1, data, data_len); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = l2_packet_send(hapd->l2, dst, proto, (u8 *) buf, 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(*buf) + data_len); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_free(buf); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef CONFIG_IEEE80211R 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst, 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const u8 *data, size_t data_len) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd = ctx; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int res; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct ieee80211_mgmt *m; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t mlen; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sta_info *sta; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sta = ap_get_sta(hapd, dst); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sta == NULL || sta->wpa_sm == NULL) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m = os_zalloc(sizeof(*m) + data_len); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (m == NULL) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mlen = ((u8 *) &m->u - (u8 *) m) + data_len; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WLAN_FC_STYPE_ACTION); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_memcpy(m->da, dst, ETH_ALEN); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_memcpy(m->sa, hapd->own_addr, ETH_ALEN); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_memcpy(&m->u, data, data_len); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen, 0); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_free(m); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return res; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct wpa_state_machine * 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd = ctx; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sta_info *sta; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sta = ap_sta_add(hapd, sta_addr); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sta == NULL) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sta->wpa_sm) { 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sta->auth_alg = WLAN_AUTH_FT; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sta->wpa_sm; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sta->wpa_sm == NULL) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ap_free_sta(hapd, sta); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sta->auth_alg = WLAN_AUTH_FT; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sta->wpa_sm; 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf, 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t len) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostapd_data *hapd = ctx; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct l2_ethhdr *ethhdr; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len < sizeof(*ethhdr)) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ethhdr = (struct l2_ethhdr *) buf; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> " 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MACSTR, MAC2STR(ethhdr->h_source), MAC2STR(ethhdr->h_dest)); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wpa_ft_rrb_rx(hapd->wpa_auth, ethhdr->h_source, buf + sizeof(*ethhdr), 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len - sizeof(*ethhdr)); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* CONFIG_IEEE80211R */ 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int hostapd_setup_wpa(struct hostapd_data *hapd) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct wpa_auth_config _conf; 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct wpa_auth_callbacks cb; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const u8 *wpa_ie; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t wpa_ie_len; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hostapd_wpa_auth_conf(hapd->conf, &_conf); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS) 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _conf.tx_status = 1; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_memset(&cb, 0, sizeof(cb)); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.ctx = hapd; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.logger = hostapd_wpa_auth_logger; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.disconnect = hostapd_wpa_auth_disconnect; 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.mic_failure_report = hostapd_wpa_auth_mic_failure_report; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.set_eapol = hostapd_wpa_auth_set_eapol; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.get_eapol = hostapd_wpa_auth_get_eapol; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.get_psk = hostapd_wpa_auth_get_psk; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.get_msk = hostapd_wpa_auth_get_msk; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.set_key = hostapd_wpa_auth_set_key; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.get_seqnum = hostapd_wpa_auth_get_seqnum; 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.send_eapol = hostapd_wpa_auth_send_eapol; 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.for_each_sta = hostapd_wpa_auth_for_each_sta; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.for_each_auth = hostapd_wpa_auth_for_each_auth; 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.send_ether = hostapd_wpa_auth_send_ether; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef CONFIG_IEEE80211R 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.send_ft_action = hostapd_wpa_auth_send_ft_action; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.add_sta = hostapd_wpa_auth_add_sta; 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* CONFIG_IEEE80211R */ 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb); 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hapd->wpa_auth == NULL) { 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wpa_printf(MSG_ERROR, "WPA initialization failed."); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hostapd_set_privacy(hapd, 1)) { 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wpa_printf(MSG_ERROR, "Could not set PrivacyInvoked " 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "for interface %s", hapd->conf->iface); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) { 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wpa_printf(MSG_ERROR, "Failed to configure WPA IE for " 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "the kernel driver."); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rsn_preauth_iface_init(hapd)) { 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wpa_printf(MSG_ERROR, "Initialization of RSN " 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "pre-authentication failed."); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef CONFIG_IEEE80211R 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!hostapd_drv_none(hapd)) { 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ? 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hapd->conf->bridge : 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hapd->conf->iface, NULL, ETH_P_RRB, 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hostapd_rrb_receive, hapd, 1); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hapd->l2 == NULL && 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (hapd->driver == NULL || 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hapd->driver->send_ether == NULL)) { 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wpa_printf(MSG_ERROR, "Failed to open l2_packet " 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "interface"); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* CONFIG_IEEE80211R */ 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void hostapd_reconfig_wpa(struct hostapd_data *hapd) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct wpa_auth_config wpa_auth_conf; 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hostapd_wpa_auth_conf(hapd->conf, &wpa_auth_conf); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void hostapd_deinit_wpa(struct hostapd_data *hapd) 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ieee80211_tkip_countermeasures_deinit(hapd); 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rsn_preauth_iface_deinit(hapd); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hapd->wpa_auth) { 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wpa_deinit(hapd->wpa_auth); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hapd->wpa_auth = NULL; 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hostapd_set_privacy(hapd, 0)) { 556 wpa_printf(MSG_DEBUG, "Could not disable " 557 "PrivacyInvoked for interface %s", 558 hapd->conf->iface); 559 } 560 561 if (hostapd_set_generic_elem(hapd, (u8 *) "", 0)) { 562 wpa_printf(MSG_DEBUG, "Could not remove generic " 563 "information element from interface %s", 564 hapd->conf->iface); 565 } 566 } 567 ieee802_1x_deinit(hapd); 568 569#ifdef CONFIG_IEEE80211R 570 l2_packet_deinit(hapd->l2); 571#endif /* CONFIG_IEEE80211R */ 572} 573