1e28a4053SRui Paulo /* 2e28a4053SRui Paulo * hostapd / WPA authenticator glue code 3*f05cddf9SRui Paulo * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi> 4e28a4053SRui Paulo * 5*f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6*f05cddf9SRui Paulo * See README for more details. 7e28a4053SRui Paulo */ 8e28a4053SRui Paulo 9e28a4053SRui Paulo #include "utils/includes.h" 10e28a4053SRui Paulo 11e28a4053SRui Paulo #include "utils/common.h" 12e28a4053SRui Paulo #include "common/ieee802_11_defs.h" 13e28a4053SRui Paulo #include "eapol_auth/eapol_auth_sm.h" 14e28a4053SRui Paulo #include "eapol_auth/eapol_auth_sm_i.h" 15e28a4053SRui Paulo #include "eap_server/eap.h" 16e28a4053SRui Paulo #include "l2_packet/l2_packet.h" 17e28a4053SRui Paulo #include "drivers/driver.h" 18e28a4053SRui Paulo #include "hostapd.h" 19e28a4053SRui Paulo #include "ieee802_1x.h" 20e28a4053SRui Paulo #include "preauth_auth.h" 21e28a4053SRui Paulo #include "sta_info.h" 22e28a4053SRui Paulo #include "tkip_countermeasures.h" 23e28a4053SRui Paulo #include "ap_drv_ops.h" 24e28a4053SRui Paulo #include "ap_config.h" 25e28a4053SRui Paulo #include "wpa_auth.h" 26*f05cddf9SRui Paulo #include "wpa_auth_glue.h" 27e28a4053SRui Paulo 28e28a4053SRui Paulo 29e28a4053SRui Paulo static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, 30e28a4053SRui Paulo struct wpa_auth_config *wconf) 31e28a4053SRui Paulo { 32*f05cddf9SRui Paulo os_memset(wconf, 0, sizeof(*wconf)); 33e28a4053SRui Paulo wconf->wpa = conf->wpa; 34e28a4053SRui Paulo wconf->wpa_key_mgmt = conf->wpa_key_mgmt; 35e28a4053SRui Paulo wconf->wpa_pairwise = conf->wpa_pairwise; 36e28a4053SRui Paulo wconf->wpa_group = conf->wpa_group; 37e28a4053SRui Paulo wconf->wpa_group_rekey = conf->wpa_group_rekey; 38e28a4053SRui Paulo wconf->wpa_strict_rekey = conf->wpa_strict_rekey; 39e28a4053SRui Paulo wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey; 40e28a4053SRui Paulo wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey; 41e28a4053SRui Paulo wconf->rsn_pairwise = conf->rsn_pairwise; 42e28a4053SRui Paulo wconf->rsn_preauth = conf->rsn_preauth; 43e28a4053SRui Paulo wconf->eapol_version = conf->eapol_version; 44e28a4053SRui Paulo wconf->peerkey = conf->peerkey; 45e28a4053SRui Paulo wconf->wmm_enabled = conf->wmm_enabled; 46e28a4053SRui Paulo wconf->wmm_uapsd = conf->wmm_uapsd; 47*f05cddf9SRui Paulo wconf->disable_pmksa_caching = conf->disable_pmksa_caching; 48e28a4053SRui Paulo wconf->okc = conf->okc; 49e28a4053SRui Paulo #ifdef CONFIG_IEEE80211W 50e28a4053SRui Paulo wconf->ieee80211w = conf->ieee80211w; 51e28a4053SRui Paulo #endif /* CONFIG_IEEE80211W */ 52e28a4053SRui Paulo #ifdef CONFIG_IEEE80211R 53e28a4053SRui Paulo wconf->ssid_len = conf->ssid.ssid_len; 54e28a4053SRui Paulo if (wconf->ssid_len > SSID_LEN) 55e28a4053SRui Paulo wconf->ssid_len = SSID_LEN; 56e28a4053SRui Paulo os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len); 57e28a4053SRui Paulo os_memcpy(wconf->mobility_domain, conf->mobility_domain, 58e28a4053SRui Paulo MOBILITY_DOMAIN_ID_LEN); 59e28a4053SRui Paulo if (conf->nas_identifier && 60e28a4053SRui Paulo os_strlen(conf->nas_identifier) <= FT_R0KH_ID_MAX_LEN) { 61e28a4053SRui Paulo wconf->r0_key_holder_len = os_strlen(conf->nas_identifier); 62e28a4053SRui Paulo os_memcpy(wconf->r0_key_holder, conf->nas_identifier, 63e28a4053SRui Paulo wconf->r0_key_holder_len); 64e28a4053SRui Paulo } 65e28a4053SRui Paulo os_memcpy(wconf->r1_key_holder, conf->r1_key_holder, FT_R1KH_ID_LEN); 66e28a4053SRui Paulo wconf->r0_key_lifetime = conf->r0_key_lifetime; 67e28a4053SRui Paulo wconf->reassociation_deadline = conf->reassociation_deadline; 68e28a4053SRui Paulo wconf->r0kh_list = conf->r0kh_list; 69e28a4053SRui Paulo wconf->r1kh_list = conf->r1kh_list; 70e28a4053SRui Paulo wconf->pmk_r1_push = conf->pmk_r1_push; 71*f05cddf9SRui Paulo wconf->ft_over_ds = conf->ft_over_ds; 72e28a4053SRui Paulo #endif /* CONFIG_IEEE80211R */ 73*f05cddf9SRui Paulo #ifdef CONFIG_HS20 74*f05cddf9SRui Paulo wconf->disable_gtk = conf->disable_dgaf; 75*f05cddf9SRui Paulo #endif /* CONFIG_HS20 */ 76e28a4053SRui Paulo } 77e28a4053SRui Paulo 78e28a4053SRui Paulo 79e28a4053SRui Paulo static void hostapd_wpa_auth_logger(void *ctx, const u8 *addr, 80e28a4053SRui Paulo logger_level level, const char *txt) 81e28a4053SRui Paulo { 82e28a4053SRui Paulo #ifndef CONFIG_NO_HOSTAPD_LOGGER 83e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 84e28a4053SRui Paulo int hlevel; 85e28a4053SRui Paulo 86e28a4053SRui Paulo switch (level) { 87e28a4053SRui Paulo case LOGGER_WARNING: 88e28a4053SRui Paulo hlevel = HOSTAPD_LEVEL_WARNING; 89e28a4053SRui Paulo break; 90e28a4053SRui Paulo case LOGGER_INFO: 91e28a4053SRui Paulo hlevel = HOSTAPD_LEVEL_INFO; 92e28a4053SRui Paulo break; 93e28a4053SRui Paulo case LOGGER_DEBUG: 94e28a4053SRui Paulo default: 95e28a4053SRui Paulo hlevel = HOSTAPD_LEVEL_DEBUG; 96e28a4053SRui Paulo break; 97e28a4053SRui Paulo } 98e28a4053SRui Paulo 99e28a4053SRui Paulo hostapd_logger(hapd, addr, HOSTAPD_MODULE_WPA, hlevel, "%s", txt); 100e28a4053SRui Paulo #endif /* CONFIG_NO_HOSTAPD_LOGGER */ 101e28a4053SRui Paulo } 102e28a4053SRui Paulo 103e28a4053SRui Paulo 104e28a4053SRui Paulo static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr, 105e28a4053SRui Paulo u16 reason) 106e28a4053SRui Paulo { 107e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 108e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "%s: WPA authenticator requests disconnect: " 109e28a4053SRui Paulo "STA " MACSTR " reason %d", 110e28a4053SRui Paulo __func__, MAC2STR(addr), reason); 111e28a4053SRui Paulo ap_sta_disconnect(hapd, NULL, addr, reason); 112e28a4053SRui Paulo } 113e28a4053SRui Paulo 114e28a4053SRui Paulo 115*f05cddf9SRui Paulo static int hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr) 116e28a4053SRui Paulo { 117e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 118*f05cddf9SRui Paulo return michael_mic_failure(hapd, addr, 0); 119e28a4053SRui Paulo } 120e28a4053SRui Paulo 121e28a4053SRui Paulo 122e28a4053SRui Paulo static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr, 123e28a4053SRui Paulo wpa_eapol_variable var, int value) 124e28a4053SRui Paulo { 125e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 126e28a4053SRui Paulo struct sta_info *sta = ap_get_sta(hapd, addr); 127e28a4053SRui Paulo if (sta == NULL) 128e28a4053SRui Paulo return; 129e28a4053SRui Paulo switch (var) { 130e28a4053SRui Paulo case WPA_EAPOL_portEnabled: 131e28a4053SRui Paulo ieee802_1x_notify_port_enabled(sta->eapol_sm, value); 132e28a4053SRui Paulo break; 133e28a4053SRui Paulo case WPA_EAPOL_portValid: 134e28a4053SRui Paulo ieee802_1x_notify_port_valid(sta->eapol_sm, value); 135e28a4053SRui Paulo break; 136e28a4053SRui Paulo case WPA_EAPOL_authorized: 137e28a4053SRui Paulo ieee802_1x_set_sta_authorized(hapd, sta, value); 138e28a4053SRui Paulo break; 139e28a4053SRui Paulo case WPA_EAPOL_portControl_Auto: 140e28a4053SRui Paulo if (sta->eapol_sm) 141e28a4053SRui Paulo sta->eapol_sm->portControl = Auto; 142e28a4053SRui Paulo break; 143e28a4053SRui Paulo case WPA_EAPOL_keyRun: 144e28a4053SRui Paulo if (sta->eapol_sm) 145e28a4053SRui Paulo sta->eapol_sm->keyRun = value ? TRUE : FALSE; 146e28a4053SRui Paulo break; 147e28a4053SRui Paulo case WPA_EAPOL_keyAvailable: 148e28a4053SRui Paulo if (sta->eapol_sm) 149e28a4053SRui Paulo sta->eapol_sm->eap_if->eapKeyAvailable = 150e28a4053SRui Paulo value ? TRUE : FALSE; 151e28a4053SRui Paulo break; 152e28a4053SRui Paulo case WPA_EAPOL_keyDone: 153e28a4053SRui Paulo if (sta->eapol_sm) 154e28a4053SRui Paulo sta->eapol_sm->keyDone = value ? TRUE : FALSE; 155e28a4053SRui Paulo break; 156e28a4053SRui Paulo case WPA_EAPOL_inc_EapolFramesTx: 157e28a4053SRui Paulo if (sta->eapol_sm) 158e28a4053SRui Paulo sta->eapol_sm->dot1xAuthEapolFramesTx++; 159e28a4053SRui Paulo break; 160e28a4053SRui Paulo } 161e28a4053SRui Paulo } 162e28a4053SRui Paulo 163e28a4053SRui Paulo 164e28a4053SRui Paulo static int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr, 165e28a4053SRui Paulo wpa_eapol_variable var) 166e28a4053SRui Paulo { 167e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 168e28a4053SRui Paulo struct sta_info *sta = ap_get_sta(hapd, addr); 169e28a4053SRui Paulo if (sta == NULL || sta->eapol_sm == NULL) 170e28a4053SRui Paulo return -1; 171e28a4053SRui Paulo switch (var) { 172e28a4053SRui Paulo case WPA_EAPOL_keyRun: 173e28a4053SRui Paulo return sta->eapol_sm->keyRun; 174e28a4053SRui Paulo case WPA_EAPOL_keyAvailable: 175e28a4053SRui Paulo return sta->eapol_sm->eap_if->eapKeyAvailable; 176e28a4053SRui Paulo default: 177e28a4053SRui Paulo return -1; 178e28a4053SRui Paulo } 179e28a4053SRui Paulo } 180e28a4053SRui Paulo 181e28a4053SRui Paulo 182e28a4053SRui Paulo static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr, 183e28a4053SRui Paulo const u8 *prev_psk) 184e28a4053SRui Paulo { 185e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 186*f05cddf9SRui Paulo struct sta_info *sta = ap_get_sta(hapd, addr); 187*f05cddf9SRui Paulo const u8 *psk = hostapd_get_psk(hapd->conf, addr, prev_psk); 188*f05cddf9SRui Paulo /* 189*f05cddf9SRui Paulo * This is about to iterate over all psks, prev_psk gives the last 190*f05cddf9SRui Paulo * returned psk which should not be returned again. 191*f05cddf9SRui Paulo * logic list (all hostapd_get_psk; all sta->psk) 192*f05cddf9SRui Paulo */ 193*f05cddf9SRui Paulo if (sta && sta->psk && !psk) { 194*f05cddf9SRui Paulo struct hostapd_sta_wpa_psk_short *pos; 195*f05cddf9SRui Paulo psk = sta->psk->psk; 196*f05cddf9SRui Paulo for (pos = sta->psk; pos; pos = pos->next) { 197*f05cddf9SRui Paulo if (pos->psk == prev_psk) { 198*f05cddf9SRui Paulo psk = pos->next ? pos->next->psk : NULL; 199*f05cddf9SRui Paulo break; 200*f05cddf9SRui Paulo } 201*f05cddf9SRui Paulo } 202*f05cddf9SRui Paulo } 203*f05cddf9SRui Paulo return psk; 204e28a4053SRui Paulo } 205e28a4053SRui Paulo 206e28a4053SRui Paulo 207e28a4053SRui Paulo static int hostapd_wpa_auth_get_msk(void *ctx, const u8 *addr, u8 *msk, 208e28a4053SRui Paulo size_t *len) 209e28a4053SRui Paulo { 210e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 211e28a4053SRui Paulo const u8 *key; 212e28a4053SRui Paulo size_t keylen; 213e28a4053SRui Paulo struct sta_info *sta; 214e28a4053SRui Paulo 215e28a4053SRui Paulo sta = ap_get_sta(hapd, addr); 216e28a4053SRui Paulo if (sta == NULL) 217e28a4053SRui Paulo return -1; 218e28a4053SRui Paulo 219e28a4053SRui Paulo key = ieee802_1x_get_key(sta->eapol_sm, &keylen); 220e28a4053SRui Paulo if (key == NULL) 221e28a4053SRui Paulo return -1; 222e28a4053SRui Paulo 223e28a4053SRui Paulo if (keylen > *len) 224e28a4053SRui Paulo keylen = *len; 225e28a4053SRui Paulo os_memcpy(msk, key, keylen); 226e28a4053SRui Paulo *len = keylen; 227e28a4053SRui Paulo 228e28a4053SRui Paulo return 0; 229e28a4053SRui Paulo } 230e28a4053SRui Paulo 231e28a4053SRui Paulo 232e28a4053SRui Paulo static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, 233e28a4053SRui Paulo const u8 *addr, int idx, u8 *key, 234e28a4053SRui Paulo size_t key_len) 235e28a4053SRui Paulo { 236e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 237e28a4053SRui Paulo const char *ifname = hapd->conf->iface; 238e28a4053SRui Paulo 239e28a4053SRui Paulo if (vlan_id > 0) { 240e28a4053SRui Paulo ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id); 241e28a4053SRui Paulo if (ifname == NULL) 242e28a4053SRui Paulo return -1; 243e28a4053SRui Paulo } 244e28a4053SRui Paulo 245*f05cddf9SRui Paulo return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0, 246e28a4053SRui Paulo key, key_len); 247e28a4053SRui Paulo } 248e28a4053SRui Paulo 249e28a4053SRui Paulo 250e28a4053SRui Paulo static int hostapd_wpa_auth_get_seqnum(void *ctx, const u8 *addr, int idx, 251e28a4053SRui Paulo u8 *seq) 252e28a4053SRui Paulo { 253e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 254e28a4053SRui Paulo return hostapd_get_seqnum(hapd->conf->iface, hapd, addr, idx, seq); 255e28a4053SRui Paulo } 256e28a4053SRui Paulo 257e28a4053SRui Paulo 258e28a4053SRui Paulo static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr, 259e28a4053SRui Paulo const u8 *data, size_t data_len, 260e28a4053SRui Paulo int encrypt) 261e28a4053SRui Paulo { 262e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 263*f05cddf9SRui Paulo struct sta_info *sta; 264*f05cddf9SRui Paulo u32 flags = 0; 265*f05cddf9SRui Paulo 266*f05cddf9SRui Paulo sta = ap_get_sta(hapd, addr); 267*f05cddf9SRui Paulo if (sta) 268*f05cddf9SRui Paulo flags = hostapd_sta_flags_to_drv(sta->flags); 269*f05cddf9SRui Paulo 270*f05cddf9SRui Paulo return hostapd_drv_hapd_send_eapol(hapd, addr, data, data_len, 271*f05cddf9SRui Paulo encrypt, flags); 272e28a4053SRui Paulo } 273e28a4053SRui Paulo 274e28a4053SRui Paulo 275e28a4053SRui Paulo static int hostapd_wpa_auth_for_each_sta( 276e28a4053SRui Paulo void *ctx, int (*cb)(struct wpa_state_machine *sm, void *ctx), 277e28a4053SRui Paulo void *cb_ctx) 278e28a4053SRui Paulo { 279e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 280e28a4053SRui Paulo struct sta_info *sta; 281e28a4053SRui Paulo 282e28a4053SRui Paulo for (sta = hapd->sta_list; sta; sta = sta->next) { 283e28a4053SRui Paulo if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx)) 284e28a4053SRui Paulo return 1; 285e28a4053SRui Paulo } 286e28a4053SRui Paulo return 0; 287e28a4053SRui Paulo } 288e28a4053SRui Paulo 289e28a4053SRui Paulo 290e28a4053SRui Paulo struct wpa_auth_iface_iter_data { 291e28a4053SRui Paulo int (*cb)(struct wpa_authenticator *sm, void *ctx); 292e28a4053SRui Paulo void *cb_ctx; 293e28a4053SRui Paulo }; 294e28a4053SRui Paulo 295e28a4053SRui Paulo static int wpa_auth_iface_iter(struct hostapd_iface *iface, void *ctx) 296e28a4053SRui Paulo { 297e28a4053SRui Paulo struct wpa_auth_iface_iter_data *data = ctx; 298e28a4053SRui Paulo size_t i; 299e28a4053SRui Paulo for (i = 0; i < iface->num_bss; i++) { 300e28a4053SRui Paulo if (iface->bss[i]->wpa_auth && 301e28a4053SRui Paulo data->cb(iface->bss[i]->wpa_auth, data->cb_ctx)) 302e28a4053SRui Paulo return 1; 303e28a4053SRui Paulo } 304e28a4053SRui Paulo return 0; 305e28a4053SRui Paulo } 306e28a4053SRui Paulo 307e28a4053SRui Paulo 308e28a4053SRui Paulo static int hostapd_wpa_auth_for_each_auth( 309e28a4053SRui Paulo void *ctx, int (*cb)(struct wpa_authenticator *sm, void *ctx), 310e28a4053SRui Paulo void *cb_ctx) 311e28a4053SRui Paulo { 312e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 313e28a4053SRui Paulo struct wpa_auth_iface_iter_data data; 314*f05cddf9SRui Paulo if (hapd->iface->interfaces == NULL || 315*f05cddf9SRui Paulo hapd->iface->interfaces->for_each_interface == NULL) 316e28a4053SRui Paulo return -1; 317e28a4053SRui Paulo data.cb = cb; 318e28a4053SRui Paulo data.cb_ctx = cb_ctx; 319*f05cddf9SRui Paulo return hapd->iface->interfaces->for_each_interface( 320*f05cddf9SRui Paulo hapd->iface->interfaces, wpa_auth_iface_iter, &data); 321e28a4053SRui Paulo } 322e28a4053SRui Paulo 323e28a4053SRui Paulo 324e28a4053SRui Paulo #ifdef CONFIG_IEEE80211R 325e28a4053SRui Paulo 326e28a4053SRui Paulo struct wpa_auth_ft_iface_iter_data { 327e28a4053SRui Paulo struct hostapd_data *src_hapd; 328e28a4053SRui Paulo const u8 *dst; 329e28a4053SRui Paulo const u8 *data; 330e28a4053SRui Paulo size_t data_len; 331e28a4053SRui Paulo }; 332e28a4053SRui Paulo 333e28a4053SRui Paulo 334e28a4053SRui Paulo static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx) 335e28a4053SRui Paulo { 336e28a4053SRui Paulo struct wpa_auth_ft_iface_iter_data *idata = ctx; 337e28a4053SRui Paulo struct hostapd_data *hapd; 338e28a4053SRui Paulo size_t j; 339e28a4053SRui Paulo 340e28a4053SRui Paulo for (j = 0; j < iface->num_bss; j++) { 341e28a4053SRui Paulo hapd = iface->bss[j]; 342e28a4053SRui Paulo if (hapd == idata->src_hapd) 343e28a4053SRui Paulo continue; 344e28a4053SRui Paulo if (os_memcmp(hapd->own_addr, idata->dst, ETH_ALEN) == 0) { 345e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "FT: Send RRB data directly to " 346e28a4053SRui Paulo "locally managed BSS " MACSTR "@%s -> " 347e28a4053SRui Paulo MACSTR "@%s", 348e28a4053SRui Paulo MAC2STR(idata->src_hapd->own_addr), 349e28a4053SRui Paulo idata->src_hapd->conf->iface, 350e28a4053SRui Paulo MAC2STR(hapd->own_addr), hapd->conf->iface); 351*f05cddf9SRui Paulo wpa_ft_rrb_rx(hapd->wpa_auth, 352*f05cddf9SRui Paulo idata->src_hapd->own_addr, 353e28a4053SRui Paulo idata->data, idata->data_len); 354e28a4053SRui Paulo return 1; 355e28a4053SRui Paulo } 356e28a4053SRui Paulo } 357e28a4053SRui Paulo 358e28a4053SRui Paulo return 0; 359e28a4053SRui Paulo } 360e28a4053SRui Paulo 361e28a4053SRui Paulo #endif /* CONFIG_IEEE80211R */ 362e28a4053SRui Paulo 363e28a4053SRui Paulo 364e28a4053SRui Paulo static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto, 365e28a4053SRui Paulo const u8 *data, size_t data_len) 366e28a4053SRui Paulo { 367e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 368*f05cddf9SRui Paulo struct l2_ethhdr *buf; 369*f05cddf9SRui Paulo int ret; 370e28a4053SRui Paulo 371e28a4053SRui Paulo #ifdef CONFIG_IEEE80211R 372*f05cddf9SRui Paulo if (proto == ETH_P_RRB && hapd->iface->interfaces && 373*f05cddf9SRui Paulo hapd->iface->interfaces->for_each_interface) { 374e28a4053SRui Paulo int res; 375e28a4053SRui Paulo struct wpa_auth_ft_iface_iter_data idata; 376e28a4053SRui Paulo idata.src_hapd = hapd; 377e28a4053SRui Paulo idata.dst = dst; 378e28a4053SRui Paulo idata.data = data; 379e28a4053SRui Paulo idata.data_len = data_len; 380*f05cddf9SRui Paulo res = hapd->iface->interfaces->for_each_interface( 381*f05cddf9SRui Paulo hapd->iface->interfaces, hostapd_wpa_auth_ft_iter, 382e28a4053SRui Paulo &idata); 383e28a4053SRui Paulo if (res == 1) 384e28a4053SRui Paulo return data_len; 385e28a4053SRui Paulo } 386e28a4053SRui Paulo #endif /* CONFIG_IEEE80211R */ 387e28a4053SRui Paulo 388e28a4053SRui Paulo if (hapd->driver && hapd->driver->send_ether) 389e28a4053SRui Paulo return hapd->driver->send_ether(hapd->drv_priv, dst, 390e28a4053SRui Paulo hapd->own_addr, proto, 391e28a4053SRui Paulo data, data_len); 392e28a4053SRui Paulo if (hapd->l2 == NULL) 393e28a4053SRui Paulo return -1; 394*f05cddf9SRui Paulo 395*f05cddf9SRui Paulo buf = os_malloc(sizeof(*buf) + data_len); 396*f05cddf9SRui Paulo if (buf == NULL) 397*f05cddf9SRui Paulo return -1; 398*f05cddf9SRui Paulo os_memcpy(buf->h_dest, dst, ETH_ALEN); 399*f05cddf9SRui Paulo os_memcpy(buf->h_source, hapd->own_addr, ETH_ALEN); 400*f05cddf9SRui Paulo buf->h_proto = host_to_be16(proto); 401*f05cddf9SRui Paulo os_memcpy(buf + 1, data, data_len); 402*f05cddf9SRui Paulo ret = l2_packet_send(hapd->l2, dst, proto, (u8 *) buf, 403*f05cddf9SRui Paulo sizeof(*buf) + data_len); 404*f05cddf9SRui Paulo os_free(buf); 405*f05cddf9SRui Paulo return ret; 406e28a4053SRui Paulo } 407e28a4053SRui Paulo 408e28a4053SRui Paulo 409e28a4053SRui Paulo #ifdef CONFIG_IEEE80211R 410e28a4053SRui Paulo 411e28a4053SRui Paulo static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst, 412e28a4053SRui Paulo const u8 *data, size_t data_len) 413e28a4053SRui Paulo { 414e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 415e28a4053SRui Paulo int res; 416e28a4053SRui Paulo struct ieee80211_mgmt *m; 417e28a4053SRui Paulo size_t mlen; 418e28a4053SRui Paulo struct sta_info *sta; 419e28a4053SRui Paulo 420e28a4053SRui Paulo sta = ap_get_sta(hapd, dst); 421e28a4053SRui Paulo if (sta == NULL || sta->wpa_sm == NULL) 422e28a4053SRui Paulo return -1; 423e28a4053SRui Paulo 424e28a4053SRui Paulo m = os_zalloc(sizeof(*m) + data_len); 425e28a4053SRui Paulo if (m == NULL) 426e28a4053SRui Paulo return -1; 427e28a4053SRui Paulo mlen = ((u8 *) &m->u - (u8 *) m) + data_len; 428e28a4053SRui Paulo m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 429e28a4053SRui Paulo WLAN_FC_STYPE_ACTION); 430e28a4053SRui Paulo os_memcpy(m->da, dst, ETH_ALEN); 431e28a4053SRui Paulo os_memcpy(m->sa, hapd->own_addr, ETH_ALEN); 432e28a4053SRui Paulo os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN); 433e28a4053SRui Paulo os_memcpy(&m->u, data, data_len); 434e28a4053SRui Paulo 435*f05cddf9SRui Paulo res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen, 0); 436e28a4053SRui Paulo os_free(m); 437e28a4053SRui Paulo return res; 438e28a4053SRui Paulo } 439e28a4053SRui Paulo 440e28a4053SRui Paulo 441e28a4053SRui Paulo static struct wpa_state_machine * 442e28a4053SRui Paulo hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr) 443e28a4053SRui Paulo { 444e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 445e28a4053SRui Paulo struct sta_info *sta; 446e28a4053SRui Paulo 447*f05cddf9SRui Paulo if (hostapd_add_sta_node(hapd, sta_addr, WLAN_AUTH_FT) < 0) 448*f05cddf9SRui Paulo return NULL; 449*f05cddf9SRui Paulo 450e28a4053SRui Paulo sta = ap_sta_add(hapd, sta_addr); 451e28a4053SRui Paulo if (sta == NULL) 452e28a4053SRui Paulo return NULL; 453e28a4053SRui Paulo if (sta->wpa_sm) { 454e28a4053SRui Paulo sta->auth_alg = WLAN_AUTH_FT; 455e28a4053SRui Paulo return sta->wpa_sm; 456e28a4053SRui Paulo } 457e28a4053SRui Paulo 458e28a4053SRui Paulo sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr); 459e28a4053SRui Paulo if (sta->wpa_sm == NULL) { 460e28a4053SRui Paulo ap_free_sta(hapd, sta); 461e28a4053SRui Paulo return NULL; 462e28a4053SRui Paulo } 463e28a4053SRui Paulo sta->auth_alg = WLAN_AUTH_FT; 464e28a4053SRui Paulo 465e28a4053SRui Paulo return sta->wpa_sm; 466e28a4053SRui Paulo } 467e28a4053SRui Paulo 468e28a4053SRui Paulo 469e28a4053SRui Paulo static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf, 470e28a4053SRui Paulo size_t len) 471e28a4053SRui Paulo { 472e28a4053SRui Paulo struct hostapd_data *hapd = ctx; 473*f05cddf9SRui Paulo struct l2_ethhdr *ethhdr; 474*f05cddf9SRui Paulo if (len < sizeof(*ethhdr)) 475*f05cddf9SRui Paulo return; 476*f05cddf9SRui Paulo ethhdr = (struct l2_ethhdr *) buf; 477*f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> " 478*f05cddf9SRui Paulo MACSTR, MAC2STR(ethhdr->h_source), MAC2STR(ethhdr->h_dest)); 479*f05cddf9SRui Paulo wpa_ft_rrb_rx(hapd->wpa_auth, ethhdr->h_source, buf + sizeof(*ethhdr), 480*f05cddf9SRui Paulo len - sizeof(*ethhdr)); 481*f05cddf9SRui Paulo } 482*f05cddf9SRui Paulo 483*f05cddf9SRui Paulo 484*f05cddf9SRui Paulo static int hostapd_wpa_auth_add_tspec(void *ctx, const u8 *sta_addr, 485*f05cddf9SRui Paulo u8 *tspec_ie, size_t tspec_ielen) 486*f05cddf9SRui Paulo { 487*f05cddf9SRui Paulo struct hostapd_data *hapd = ctx; 488*f05cddf9SRui Paulo return hostapd_add_tspec(hapd, sta_addr, tspec_ie, tspec_ielen); 489e28a4053SRui Paulo } 490e28a4053SRui Paulo 491e28a4053SRui Paulo #endif /* CONFIG_IEEE80211R */ 492e28a4053SRui Paulo 493e28a4053SRui Paulo 494e28a4053SRui Paulo int hostapd_setup_wpa(struct hostapd_data *hapd) 495e28a4053SRui Paulo { 496e28a4053SRui Paulo struct wpa_auth_config _conf; 497e28a4053SRui Paulo struct wpa_auth_callbacks cb; 498e28a4053SRui Paulo const u8 *wpa_ie; 499e28a4053SRui Paulo size_t wpa_ie_len; 500e28a4053SRui Paulo 501e28a4053SRui Paulo hostapd_wpa_auth_conf(hapd->conf, &_conf); 502*f05cddf9SRui Paulo if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS) 503*f05cddf9SRui Paulo _conf.tx_status = 1; 504*f05cddf9SRui Paulo if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME) 505*f05cddf9SRui Paulo _conf.ap_mlme = 1; 506e28a4053SRui Paulo os_memset(&cb, 0, sizeof(cb)); 507e28a4053SRui Paulo cb.ctx = hapd; 508e28a4053SRui Paulo cb.logger = hostapd_wpa_auth_logger; 509e28a4053SRui Paulo cb.disconnect = hostapd_wpa_auth_disconnect; 510e28a4053SRui Paulo cb.mic_failure_report = hostapd_wpa_auth_mic_failure_report; 511e28a4053SRui Paulo cb.set_eapol = hostapd_wpa_auth_set_eapol; 512e28a4053SRui Paulo cb.get_eapol = hostapd_wpa_auth_get_eapol; 513e28a4053SRui Paulo cb.get_psk = hostapd_wpa_auth_get_psk; 514e28a4053SRui Paulo cb.get_msk = hostapd_wpa_auth_get_msk; 515e28a4053SRui Paulo cb.set_key = hostapd_wpa_auth_set_key; 516e28a4053SRui Paulo cb.get_seqnum = hostapd_wpa_auth_get_seqnum; 517e28a4053SRui Paulo cb.send_eapol = hostapd_wpa_auth_send_eapol; 518e28a4053SRui Paulo cb.for_each_sta = hostapd_wpa_auth_for_each_sta; 519e28a4053SRui Paulo cb.for_each_auth = hostapd_wpa_auth_for_each_auth; 520e28a4053SRui Paulo cb.send_ether = hostapd_wpa_auth_send_ether; 521e28a4053SRui Paulo #ifdef CONFIG_IEEE80211R 522e28a4053SRui Paulo cb.send_ft_action = hostapd_wpa_auth_send_ft_action; 523e28a4053SRui Paulo cb.add_sta = hostapd_wpa_auth_add_sta; 524*f05cddf9SRui Paulo cb.add_tspec = hostapd_wpa_auth_add_tspec; 525e28a4053SRui Paulo #endif /* CONFIG_IEEE80211R */ 526e28a4053SRui Paulo hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb); 527e28a4053SRui Paulo if (hapd->wpa_auth == NULL) { 528e28a4053SRui Paulo wpa_printf(MSG_ERROR, "WPA initialization failed."); 529e28a4053SRui Paulo return -1; 530e28a4053SRui Paulo } 531e28a4053SRui Paulo 532e28a4053SRui Paulo if (hostapd_set_privacy(hapd, 1)) { 533e28a4053SRui Paulo wpa_printf(MSG_ERROR, "Could not set PrivacyInvoked " 534e28a4053SRui Paulo "for interface %s", hapd->conf->iface); 535e28a4053SRui Paulo return -1; 536e28a4053SRui Paulo } 537e28a4053SRui Paulo 538e28a4053SRui Paulo wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len); 539e28a4053SRui Paulo if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) { 540e28a4053SRui Paulo wpa_printf(MSG_ERROR, "Failed to configure WPA IE for " 541e28a4053SRui Paulo "the kernel driver."); 542e28a4053SRui Paulo return -1; 543e28a4053SRui Paulo } 544e28a4053SRui Paulo 545e28a4053SRui Paulo if (rsn_preauth_iface_init(hapd)) { 546e28a4053SRui Paulo wpa_printf(MSG_ERROR, "Initialization of RSN " 547e28a4053SRui Paulo "pre-authentication failed."); 548e28a4053SRui Paulo return -1; 549e28a4053SRui Paulo } 550e28a4053SRui Paulo 551e28a4053SRui Paulo #ifdef CONFIG_IEEE80211R 552e28a4053SRui Paulo if (!hostapd_drv_none(hapd)) { 553e28a4053SRui Paulo hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ? 554e28a4053SRui Paulo hapd->conf->bridge : 555e28a4053SRui Paulo hapd->conf->iface, NULL, ETH_P_RRB, 556*f05cddf9SRui Paulo hostapd_rrb_receive, hapd, 1); 557e28a4053SRui Paulo if (hapd->l2 == NULL && 558e28a4053SRui Paulo (hapd->driver == NULL || 559e28a4053SRui Paulo hapd->driver->send_ether == NULL)) { 560e28a4053SRui Paulo wpa_printf(MSG_ERROR, "Failed to open l2_packet " 561e28a4053SRui Paulo "interface"); 562e28a4053SRui Paulo return -1; 563e28a4053SRui Paulo } 564e28a4053SRui Paulo } 565e28a4053SRui Paulo #endif /* CONFIG_IEEE80211R */ 566e28a4053SRui Paulo 567e28a4053SRui Paulo return 0; 568e28a4053SRui Paulo 569e28a4053SRui Paulo } 570e28a4053SRui Paulo 571e28a4053SRui Paulo 572e28a4053SRui Paulo void hostapd_reconfig_wpa(struct hostapd_data *hapd) 573e28a4053SRui Paulo { 574e28a4053SRui Paulo struct wpa_auth_config wpa_auth_conf; 575e28a4053SRui Paulo hostapd_wpa_auth_conf(hapd->conf, &wpa_auth_conf); 576e28a4053SRui Paulo wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf); 577e28a4053SRui Paulo } 578e28a4053SRui Paulo 579e28a4053SRui Paulo 580e28a4053SRui Paulo void hostapd_deinit_wpa(struct hostapd_data *hapd) 581e28a4053SRui Paulo { 582*f05cddf9SRui Paulo ieee80211_tkip_countermeasures_deinit(hapd); 583e28a4053SRui Paulo rsn_preauth_iface_deinit(hapd); 584e28a4053SRui Paulo if (hapd->wpa_auth) { 585e28a4053SRui Paulo wpa_deinit(hapd->wpa_auth); 586e28a4053SRui Paulo hapd->wpa_auth = NULL; 587e28a4053SRui Paulo 588e28a4053SRui Paulo if (hostapd_set_privacy(hapd, 0)) { 589e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "Could not disable " 590e28a4053SRui Paulo "PrivacyInvoked for interface %s", 591e28a4053SRui Paulo hapd->conf->iface); 592e28a4053SRui Paulo } 593e28a4053SRui Paulo 594e28a4053SRui Paulo if (hostapd_set_generic_elem(hapd, (u8 *) "", 0)) { 595e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "Could not remove generic " 596e28a4053SRui Paulo "information element from interface %s", 597e28a4053SRui Paulo hapd->conf->iface); 598e28a4053SRui Paulo } 599e28a4053SRui Paulo } 600e28a4053SRui Paulo ieee802_1x_deinit(hapd); 601e28a4053SRui Paulo 602e28a4053SRui Paulo #ifdef CONFIG_IEEE80211R 603e28a4053SRui Paulo l2_packet_deinit(hapd->l2); 604e28a4053SRui Paulo #endif /* CONFIG_IEEE80211R */ 605e28a4053SRui Paulo } 606