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