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