1214501Srpaulo/* 2214501Srpaulo * hostapd - Authenticator for IEEE 802.11i RSN pre-authentication 3214501Srpaulo * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> 4214501Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214501Srpaulo */ 8214501Srpaulo 9214501Srpaulo#include "utils/includes.h" 10214501Srpaulo 11214501Srpaulo#ifdef CONFIG_RSN_PREAUTH 12214501Srpaulo 13214501Srpaulo#include "utils/common.h" 14214501Srpaulo#include "utils/eloop.h" 15214501Srpaulo#include "l2_packet/l2_packet.h" 16214501Srpaulo#include "common/wpa_common.h" 17214501Srpaulo#include "eapol_auth/eapol_auth_sm.h" 18214501Srpaulo#include "eapol_auth/eapol_auth_sm_i.h" 19214501Srpaulo#include "hostapd.h" 20214501Srpaulo#include "ap_config.h" 21214501Srpaulo#include "ieee802_1x.h" 22214501Srpaulo#include "sta_info.h" 23214501Srpaulo#include "wpa_auth.h" 24214501Srpaulo#include "preauth_auth.h" 25214501Srpaulo 26214501Srpaulo#ifndef ETH_P_PREAUTH 27214501Srpaulo#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ 28214501Srpaulo#endif /* ETH_P_PREAUTH */ 29214501Srpaulo 30214501Srpaulostatic const int dot11RSNAConfigPMKLifetime = 43200; 31214501Srpaulo 32214501Srpaulostruct rsn_preauth_interface { 33214501Srpaulo struct rsn_preauth_interface *next; 34214501Srpaulo struct hostapd_data *hapd; 35214501Srpaulo struct l2_packet_data *l2; 36214501Srpaulo char *ifname; 37214501Srpaulo int ifindex; 38214501Srpaulo}; 39214501Srpaulo 40214501Srpaulo 41214501Srpaulostatic void rsn_preauth_receive(void *ctx, const u8 *src_addr, 42214501Srpaulo const u8 *buf, size_t len) 43214501Srpaulo{ 44214501Srpaulo struct rsn_preauth_interface *piface = ctx; 45214501Srpaulo struct hostapd_data *hapd = piface->hapd; 46214501Srpaulo struct ieee802_1x_hdr *hdr; 47214501Srpaulo struct sta_info *sta; 48214501Srpaulo struct l2_ethhdr *ethhdr; 49214501Srpaulo 50214501Srpaulo wpa_printf(MSG_DEBUG, "RSN: receive pre-auth packet " 51214501Srpaulo "from interface '%s'", piface->ifname); 52214501Srpaulo if (len < sizeof(*ethhdr) + sizeof(*hdr)) { 53214501Srpaulo wpa_printf(MSG_DEBUG, "RSN: too short pre-auth packet " 54214501Srpaulo "(len=%lu)", (unsigned long) len); 55214501Srpaulo return; 56214501Srpaulo } 57214501Srpaulo 58214501Srpaulo ethhdr = (struct l2_ethhdr *) buf; 59214501Srpaulo hdr = (struct ieee802_1x_hdr *) (ethhdr + 1); 60214501Srpaulo 61214501Srpaulo if (os_memcmp(ethhdr->h_dest, hapd->own_addr, ETH_ALEN) != 0) { 62214501Srpaulo wpa_printf(MSG_DEBUG, "RSN: pre-auth for foreign address " 63214501Srpaulo MACSTR, MAC2STR(ethhdr->h_dest)); 64214501Srpaulo return; 65214501Srpaulo } 66214501Srpaulo 67214501Srpaulo sta = ap_get_sta(hapd, ethhdr->h_source); 68214501Srpaulo if (sta && (sta->flags & WLAN_STA_ASSOC)) { 69214501Srpaulo wpa_printf(MSG_DEBUG, "RSN: pre-auth for already association " 70214501Srpaulo "STA " MACSTR, MAC2STR(sta->addr)); 71214501Srpaulo return; 72214501Srpaulo } 73214501Srpaulo if (!sta && hdr->type == IEEE802_1X_TYPE_EAPOL_START) { 74214501Srpaulo sta = ap_sta_add(hapd, ethhdr->h_source); 75214501Srpaulo if (sta == NULL) 76214501Srpaulo return; 77214501Srpaulo sta->flags = WLAN_STA_PREAUTH; 78214501Srpaulo 79214501Srpaulo ieee802_1x_new_station(hapd, sta); 80214501Srpaulo if (sta->eapol_sm == NULL) { 81214501Srpaulo ap_free_sta(hapd, sta); 82214501Srpaulo sta = NULL; 83214501Srpaulo } else { 84214501Srpaulo sta->eapol_sm->radius_identifier = -1; 85214501Srpaulo sta->eapol_sm->portValid = TRUE; 86214501Srpaulo sta->eapol_sm->flags |= EAPOL_SM_PREAUTH; 87214501Srpaulo } 88214501Srpaulo } 89214501Srpaulo if (sta == NULL) 90214501Srpaulo return; 91214501Srpaulo sta->preauth_iface = piface; 92214501Srpaulo ieee802_1x_receive(hapd, ethhdr->h_source, (u8 *) (ethhdr + 1), 93214501Srpaulo len - sizeof(*ethhdr)); 94214501Srpaulo} 95214501Srpaulo 96214501Srpaulo 97214501Srpaulostatic int rsn_preauth_iface_add(struct hostapd_data *hapd, const char *ifname) 98214501Srpaulo{ 99214501Srpaulo struct rsn_preauth_interface *piface; 100214501Srpaulo 101214501Srpaulo wpa_printf(MSG_DEBUG, "RSN pre-auth interface '%s'", ifname); 102214501Srpaulo 103214501Srpaulo piface = os_zalloc(sizeof(*piface)); 104214501Srpaulo if (piface == NULL) 105214501Srpaulo return -1; 106214501Srpaulo piface->hapd = hapd; 107214501Srpaulo 108214501Srpaulo piface->ifname = os_strdup(ifname); 109214501Srpaulo if (piface->ifname == NULL) { 110214501Srpaulo goto fail1; 111214501Srpaulo } 112214501Srpaulo 113214501Srpaulo piface->l2 = l2_packet_init(piface->ifname, NULL, ETH_P_PREAUTH, 114214501Srpaulo rsn_preauth_receive, piface, 1); 115214501Srpaulo if (piface->l2 == NULL) { 116214501Srpaulo wpa_printf(MSG_ERROR, "Failed to open register layer 2 access " 117214501Srpaulo "to ETH_P_PREAUTH"); 118214501Srpaulo goto fail2; 119214501Srpaulo } 120214501Srpaulo 121214501Srpaulo piface->next = hapd->preauth_iface; 122214501Srpaulo hapd->preauth_iface = piface; 123214501Srpaulo return 0; 124214501Srpaulo 125214501Srpaulofail2: 126214501Srpaulo os_free(piface->ifname); 127214501Srpaulofail1: 128214501Srpaulo os_free(piface); 129214501Srpaulo return -1; 130214501Srpaulo} 131214501Srpaulo 132214501Srpaulo 133214501Srpaulovoid rsn_preauth_iface_deinit(struct hostapd_data *hapd) 134214501Srpaulo{ 135214501Srpaulo struct rsn_preauth_interface *piface, *prev; 136214501Srpaulo 137214501Srpaulo piface = hapd->preauth_iface; 138214501Srpaulo hapd->preauth_iface = NULL; 139214501Srpaulo while (piface) { 140214501Srpaulo prev = piface; 141214501Srpaulo piface = piface->next; 142214501Srpaulo l2_packet_deinit(prev->l2); 143214501Srpaulo os_free(prev->ifname); 144214501Srpaulo os_free(prev); 145214501Srpaulo } 146214501Srpaulo} 147214501Srpaulo 148214501Srpaulo 149214501Srpauloint rsn_preauth_iface_init(struct hostapd_data *hapd) 150214501Srpaulo{ 151214501Srpaulo char *tmp, *start, *end; 152214501Srpaulo 153214501Srpaulo if (hapd->conf->rsn_preauth_interfaces == NULL) 154214501Srpaulo return 0; 155214501Srpaulo 156214501Srpaulo tmp = os_strdup(hapd->conf->rsn_preauth_interfaces); 157214501Srpaulo if (tmp == NULL) 158214501Srpaulo return -1; 159214501Srpaulo start = tmp; 160214501Srpaulo for (;;) { 161214501Srpaulo while (*start == ' ') 162214501Srpaulo start++; 163214501Srpaulo if (*start == '\0') 164214501Srpaulo break; 165214501Srpaulo end = os_strchr(start, ' '); 166214501Srpaulo if (end) 167214501Srpaulo *end = '\0'; 168214501Srpaulo 169214501Srpaulo if (rsn_preauth_iface_add(hapd, start)) { 170214501Srpaulo rsn_preauth_iface_deinit(hapd); 171214501Srpaulo os_free(tmp); 172214501Srpaulo return -1; 173214501Srpaulo } 174214501Srpaulo 175214501Srpaulo if (end) 176214501Srpaulo start = end + 1; 177214501Srpaulo else 178214501Srpaulo break; 179214501Srpaulo } 180214501Srpaulo os_free(tmp); 181214501Srpaulo return 0; 182214501Srpaulo} 183214501Srpaulo 184214501Srpaulo 185214501Srpaulostatic void rsn_preauth_finished_cb(void *eloop_ctx, void *timeout_ctx) 186214501Srpaulo{ 187214501Srpaulo struct hostapd_data *hapd = eloop_ctx; 188214501Srpaulo struct sta_info *sta = timeout_ctx; 189214501Srpaulo wpa_printf(MSG_DEBUG, "RSN: Removing pre-authentication STA entry for " 190214501Srpaulo MACSTR, MAC2STR(sta->addr)); 191214501Srpaulo ap_free_sta(hapd, sta); 192214501Srpaulo} 193214501Srpaulo 194214501Srpaulo 195214501Srpaulovoid rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta, 196214501Srpaulo int success) 197214501Srpaulo{ 198214501Srpaulo const u8 *key; 199214501Srpaulo size_t len; 200214501Srpaulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, 201214501Srpaulo HOSTAPD_LEVEL_INFO, "pre-authentication %s", 202214501Srpaulo success ? "succeeded" : "failed"); 203214501Srpaulo 204214501Srpaulo key = ieee802_1x_get_key(sta->eapol_sm, &len); 205214501Srpaulo if (len > PMK_LEN) 206214501Srpaulo len = PMK_LEN; 207214501Srpaulo if (success && key) { 208214501Srpaulo if (wpa_auth_pmksa_add_preauth(hapd->wpa_auth, key, len, 209214501Srpaulo sta->addr, 210214501Srpaulo dot11RSNAConfigPMKLifetime, 211214501Srpaulo sta->eapol_sm) == 0) { 212214501Srpaulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, 213214501Srpaulo HOSTAPD_LEVEL_DEBUG, 214214501Srpaulo "added PMKSA cache entry (pre-auth)"); 215214501Srpaulo } else { 216214501Srpaulo hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, 217214501Srpaulo HOSTAPD_LEVEL_DEBUG, 218214501Srpaulo "failed to add PMKSA cache entry " 219214501Srpaulo "(pre-auth)"); 220214501Srpaulo } 221214501Srpaulo } 222214501Srpaulo 223214501Srpaulo /* 224214501Srpaulo * Finish STA entry removal from timeout in order to avoid freeing 225214501Srpaulo * STA data before the caller has finished processing. 226214501Srpaulo */ 227214501Srpaulo eloop_register_timeout(0, 0, rsn_preauth_finished_cb, hapd, sta); 228214501Srpaulo} 229214501Srpaulo 230214501Srpaulo 231214501Srpaulovoid rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta, 232214501Srpaulo u8 *buf, size_t len) 233214501Srpaulo{ 234214501Srpaulo struct rsn_preauth_interface *piface; 235214501Srpaulo struct l2_ethhdr *ethhdr; 236214501Srpaulo 237214501Srpaulo piface = hapd->preauth_iface; 238214501Srpaulo while (piface) { 239214501Srpaulo if (piface == sta->preauth_iface) 240214501Srpaulo break; 241214501Srpaulo piface = piface->next; 242214501Srpaulo } 243214501Srpaulo 244214501Srpaulo if (piface == NULL) { 245214501Srpaulo wpa_printf(MSG_DEBUG, "RSN: Could not find pre-authentication " 246214501Srpaulo "interface for " MACSTR, MAC2STR(sta->addr)); 247214501Srpaulo return; 248214501Srpaulo } 249214501Srpaulo 250214501Srpaulo ethhdr = os_malloc(sizeof(*ethhdr) + len); 251214501Srpaulo if (ethhdr == NULL) 252214501Srpaulo return; 253214501Srpaulo 254214501Srpaulo os_memcpy(ethhdr->h_dest, sta->addr, ETH_ALEN); 255214501Srpaulo os_memcpy(ethhdr->h_source, hapd->own_addr, ETH_ALEN); 256214501Srpaulo ethhdr->h_proto = host_to_be16(ETH_P_PREAUTH); 257214501Srpaulo os_memcpy(ethhdr + 1, buf, len); 258214501Srpaulo 259214501Srpaulo if (l2_packet_send(piface->l2, sta->addr, ETH_P_PREAUTH, (u8 *) ethhdr, 260214501Srpaulo sizeof(*ethhdr) + len) < 0) { 261214501Srpaulo wpa_printf(MSG_ERROR, "Failed to send preauth packet using " 262214501Srpaulo "l2_packet_send\n"); 263214501Srpaulo } 264214501Srpaulo os_free(ethhdr); 265214501Srpaulo} 266214501Srpaulo 267214501Srpaulo 268214501Srpaulovoid rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta) 269214501Srpaulo{ 270214501Srpaulo eloop_cancel_timeout(rsn_preauth_finished_cb, hapd, sta); 271214501Srpaulo} 272214501Srpaulo 273214501Srpaulo#endif /* CONFIG_RSN_PREAUTH */ 274