1 /*
2  * hostapd / IEEE 802.1X-2004 Authenticator
3  * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "utils/includes.h"
10 
11 #include "utils/common.h"
12 #include "crypto/crypto.h"
13 #include "common/ieee802_11_defs.h"
14 #include "hostapd.h"
15 #include "ap/sta_info.h"
16 #include "ap/wpa_auth.h"
17 #include "ap/ap_config.h"
18 #include "ap/ieee802_1x.h"
19 #include "utils/wpa_debug.h"
20 
21 /**
22  * ieee802_1x_receive - Process the EAPOL frames from the Supplicant
23  * @hapd: hostapd BSS data
24  * @sa: Source address (sender of the EAPOL frame)
25  * @buf: EAPOL frame
26  * @len: Length of buf in octets
27  *
28  * This function is called for each incoming EAPOL frame from the interface
29  */
ieee802_1x_receive(struct hostapd_data * hapd,const u8 * sa,const u8 * buf,size_t len)30 void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
31 			size_t len)
32 {
33 	struct sta_info *sta;
34 	struct ieee802_1x_hdr *hdr;
35 	struct ieee802_1x_eapol_key *key;
36 	u16 datalen;
37 
38 	wpa_printf( MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR,
39 		   (unsigned long) len, MAC2STR(sa));
40 	sta = ap_get_sta(hapd, sa);
41 	if (!sta || !(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH))) {
42 		wpa_printf( MSG_DEBUG, "IEEE 802.1X data frame from not "
43 			   "associated/Pre-authenticating STA");
44 		return;
45 	}
46 
47 	if (len < sizeof(*hdr)) {
48 		wpa_printf( MSG_DEBUG, "   too short IEEE 802.1X packet\n");
49 		return;
50 	}
51 
52 	hdr = (struct ieee802_1x_hdr *) buf;
53 	datalen = be_to_host16(hdr->length);
54 	wpa_printf( MSG_DEBUG, "   IEEE 802.1X: version=%d type=%d length=%d",
55 		   hdr->version, hdr->type, datalen);
56 
57 	if (len - sizeof(*hdr) < datalen) {
58 		wpa_printf( MSG_DEBUG, "   frame too short for this IEEE 802.1X packet\n");
59 		return;
60 	}
61 	if (len - sizeof(*hdr) > datalen) {
62 		wpa_printf( MSG_DEBUG, "   ignoring %lu extra octets after "
63 			   "IEEE 802.1X packet",
64 			   (unsigned long) len - sizeof(*hdr) - datalen);
65 	}
66 
67 	key = (struct ieee802_1x_eapol_key *) (hdr + 1);
68 	if (datalen >= sizeof(struct ieee802_1x_eapol_key) &&
69 	    hdr->type == IEEE802_1X_TYPE_EAPOL_KEY &&
70 	    (key->type == EAPOL_KEY_TYPE_WPA ||
71 	     key->type == EAPOL_KEY_TYPE_RSN)) {
72 		wpa_receive(hapd->wpa_auth, sta->wpa_sm, (u8 *) hdr,
73 			    sizeof(*hdr) + datalen);
74 		return;
75 	}
76 }
77