2 * Host AP (software wireless LAN access point) user space daemon for
3 * Host AP kernel driver / IEEE 802.1X Authenticator
4 * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * Alternatively, this software may be distributed under the terms of BSD
13 * See README and COPYING for more details.
21 #include <netinet/in.h>
23 #include <sys/ioctl.h>
28 #include <sys/socket.h>
31 #include "ieee802_1x.h"
32 #include "accounting.h"
34 #include "radius_client.h"
45 static void ieee802_1x_new_auth_session(struct hostapd_data *hapd,
46 struct sta_info *sta);
49 static void ieee802_1x_send(hostapd *hapd, struct sta_info *sta, u8 type,
50 u8 *data, size_t datalen)
53 struct ieee802_1x_hdr *xhdr;
57 len = sizeof(*xhdr) + datalen;
60 printf("malloc() failed for ieee802_1x_send(len=%lu)\n",
68 * According to IEEE 802.1aa/D4 EAPOL-Key should be sent before any
69 * remaining EAP frames, if possible. This would allow rest of the
70 * frames to be encrypted. This code could be used to request
71 * encryption from the kernel driver. */
73 sta->eapol_sm->be_auth.state == BE_AUTH_SUCCESS &&
74 sta->eapol_sm->keyTxEnabled)
78 xhdr = (struct ieee802_1x_hdr *) buf;
79 xhdr->version = EAPOL_VERSION;
81 xhdr->length = htons(datalen);
83 if (datalen > 0 && data != NULL)
84 memcpy(xhdr + 1, data, datalen);
86 if (sta->wpa_sm && sta->wpa_sm->pairwise_set)
88 if (sta->flags & WLAN_STA_PREAUTH) {
89 rsn_preauth_send(hapd, sta, buf, len);
91 hostapd_send_eapol(hapd, sta->addr, buf, len, encrypt);
98 void ieee802_1x_set_sta_authorized(hostapd *hapd, struct sta_info *sta,
101 if (sta->flags & WLAN_STA_PREAUTH)
105 sta->flags |= WLAN_STA_AUTHORIZED;
106 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
107 HOSTAPD_LEVEL_DEBUG, "authorizing port");
109 sta->flags &= ~WLAN_STA_AUTHORIZED;
110 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
111 HOSTAPD_LEVEL_DEBUG, "unauthorizing port");
114 hostapd_set_sta_authorized(hapd, sta->addr, authorized);
116 accounting_sta_start(hapd, sta);
120 static void ieee802_1x_eap_timeout(void *eloop_ctx, void *timeout_ctx)
122 struct sta_info *sta = eloop_ctx;
123 struct eapol_state_machine *sm = sta->eapol_sm;
126 hostapd_logger(sm->hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
127 HOSTAPD_LEVEL_DEBUG, "EAP timeout");
128 sm->eapTimeout = TRUE;
133 void ieee802_1x_request_identity(struct hostapd_data *hapd,
134 struct sta_info *sta)
140 struct eapol_state_machine *sm = sta->eapol_sm;
142 if (hapd->conf->eap_server) {
143 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
144 "IEEE 802.1X: Integrated EAP server in "
145 "use - do not generate EAP-Request/Identity\n");
149 if (sm == NULL || !sm->auth_pae.eapRestart)
152 ieee802_1x_new_auth_session(hapd, sta);
154 tlen = sizeof(*eap) + 1 + hapd->conf->eap_req_id_text_len;
158 printf("Could not allocate memory for identity request\n");
162 memset(buf, 0, tlen);
164 eap = (struct eap_hdr *) buf;
165 eap->code = EAP_CODE_REQUEST;
166 eap->identifier = ++sm->currentId;
167 eap->length = htons(tlen);
168 pos = (u8 *) (eap + 1);
169 *pos++ = EAP_TYPE_IDENTITY;
170 if (hapd->conf->eap_req_id_text) {
171 memcpy(pos, hapd->conf->eap_req_id_text,
172 hapd->conf->eap_req_id_text_len);
175 sm->be_auth.eapReq = TRUE;
176 free(sm->last_eap_radius);
177 sm->last_eap_radius = buf;
178 sm->last_eap_radius_len = tlen;
180 eloop_cancel_timeout(ieee802_1x_eap_timeout, sta, NULL);
181 eloop_register_timeout(30, 0, ieee802_1x_eap_timeout, sta, NULL);
182 sm->eapTimeout = FALSE;
184 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
185 "IEEE 802.1X: Generated EAP Request-Identity for " MACSTR
186 " (identifier %d, timeout 30)\n", MAC2STR(sta->addr),
189 sm->auth_pae.eapRestart = FALSE;
193 void ieee802_1x_tx_canned_eap(struct hostapd_data *hapd, struct sta_info *sta,
197 struct eapol_state_machine *sm = sta->eapol_sm;
199 memset(&eap, 0, sizeof(eap));
201 eap.code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE;
203 if (sm && sm->last_eap_radius) {
204 struct eap_hdr *hdr = (struct eap_hdr *) sm->last_eap_radius;
205 eap.identifier = hdr->identifier + 1;
207 eap.length = htons(sizeof(eap));
209 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
210 "IEEE 802.1X: Sending canned EAP packet %s to " MACSTR
211 " (identifier %d)\n", success ? "SUCCESS" : "FAILURE",
212 MAC2STR(sta->addr), eap.identifier);
213 ieee802_1x_send(hapd, sta, IEEE802_1X_TYPE_EAP_PACKET, (u8 *) &eap,
216 sm->dot1xAuthEapolFramesTx++;
220 void ieee802_1x_tx_req(struct hostapd_data *hapd, struct sta_info *sta)
223 struct eapol_state_machine *sm = sta->eapol_sm;
228 if (sm->last_eap_radius == NULL) {
229 printf("Error: TxReq called for station " MACSTR ", but there "
230 "is no EAP request from the authentication server\n",
235 eap = (struct eap_hdr *) sm->last_eap_radius;
236 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
237 "IEEE 802.1X: Sending EAP Packet to " MACSTR
238 " (identifier %d)\n", MAC2STR(sm->addr),
240 sm->currentId = eap->identifier;
241 ieee802_1x_send(hapd, sta, IEEE802_1X_TYPE_EAP_PACKET,
242 sm->last_eap_radius, sm->last_eap_radius_len);
243 sm->dot1xAuthEapolFramesTx++;
244 type = (u8 *) (eap + 1);
245 if (sm->last_eap_radius_len > sizeof(*eap) &&
246 *type == EAP_TYPE_IDENTITY)
247 sm->dot1xAuthEapolReqIdFramesTx++;
249 sm->dot1xAuthEapolReqFramesTx++;
253 void hostapd_get_ntp_timestamp(u8 *buf)
258 /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
259 gettimeofday(&now, NULL);
260 sec = htonl(now.tv_sec + 2208988800U); /* Epoch to 1900 */
261 /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
263 usec = htonl(4295 * usec - (usec >> 5) - (usec >> 9));
264 memcpy(buf, (u8 *) &sec, 4);
265 memcpy(buf + 4, (u8 *) &usec, 4);
269 static void ieee802_1x_tx_key_one(hostapd *hapd, struct sta_info *sta,
270 int index, int broadcast,
271 u8 *key_data, size_t key_len)
274 struct ieee802_1x_hdr *hdr;
275 struct ieee802_1x_eapol_key *key;
276 size_t len, ekey_len;
277 struct eapol_state_machine *sm = sta->eapol_sm;
282 len = sizeof(*key) + key_len;
283 buf = malloc(sizeof(*hdr) + len);
287 memset(buf, 0, sizeof(*hdr) + len);
288 hdr = (struct ieee802_1x_hdr *) buf;
289 key = (struct ieee802_1x_eapol_key *) (hdr + 1);
290 key->type = EAPOL_KEY_TYPE_RC4;
291 key->key_length = htons(key_len);
292 hostapd_get_ntp_timestamp(key->replay_counter);
294 if (hostapd_get_rand(key->key_iv, sizeof(key->key_iv))) {
295 printf("Could not get random numbers\n");
300 key->key_index = index | (broadcast ? 0 : BIT(7));
301 if (hapd->conf->eapol_key_index_workaround) {
302 /* According to some information, WinXP Supplicant seems to
303 * interpret bit7 as an indication whether the key is to be
304 * activated, so make it possible to enable workaround that
305 * sets this bit for all keys. */
306 key->key_index |= BIT(7);
309 /* Key is encrypted using "Key-IV + sm->eapol_key_crypt" as the
311 memcpy((u8 *) (key + 1), key_data, key_len);
312 ekey_len = sizeof(key->key_iv) + sm->eapol_key_crypt_len;
313 ekey = malloc(ekey_len);
315 printf("Could not encrypt key\n");
319 memcpy(ekey, key->key_iv, sizeof(key->key_iv));
320 memcpy(ekey + sizeof(key->key_iv), sm->eapol_key_crypt,
321 sm->eapol_key_crypt_len);
322 rc4((u8 *) (key + 1), key_len, ekey, ekey_len);
325 /* This header is needed here for HMAC-MD5, but it will be regenerated
326 * in ieee802_1x_send() */
327 hdr->version = EAPOL_VERSION;
328 hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;
329 hdr->length = htons(len);
330 hmac_md5(sm->eapol_key_sign, sm->eapol_key_sign_len,
331 buf, sizeof(*hdr) + len,
334 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
335 "IEEE 802.1X: Sending EAPOL-Key to " MACSTR
336 " (%s index=%d)\n", MAC2STR(sm->addr),
337 broadcast ? "broadcast" : "unicast", index);
338 ieee802_1x_send(hapd, sta, IEEE802_1X_TYPE_EAPOL_KEY, (u8 *) key, len);
340 sta->eapol_sm->dot1xAuthEapolFramesTx++;
345 void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
347 struct eapol_state_machine *sm = sta->eapol_sm;
349 if (sm == NULL || !sm->eapol_key_sign || !sm->eapol_key_crypt)
352 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
353 "IEEE 802.1X: Sending EAPOL-Key(s) to " MACSTR "\n",
356 if (hapd->default_wep_key)
357 ieee802_1x_tx_key_one(hapd, sta, hapd->default_wep_key_idx, 1,
358 hapd->default_wep_key,
359 hapd->conf->default_wep_key_len);
361 if (hapd->conf->individual_wep_key_len > 0) {
363 ikey = malloc(hapd->conf->individual_wep_key_len);
365 hostapd_get_rand(ikey,
366 hapd->conf->individual_wep_key_len)) {
367 printf("Could not generate random individual WEP "
373 if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL))
374 hostapd_hexdump("Individual WEP key",
376 hapd->conf->individual_wep_key_len);
378 ieee802_1x_tx_key_one(hapd, sta, 0, 0, ikey,
379 hapd->conf->individual_wep_key_len);
381 /* TODO: set encryption in TX callback, i.e., only after STA
382 * has ACKed EAPOL-Key frame */
383 if (hostapd_set_encryption(hapd, "WEP", sta->addr, 0, ikey,
385 individual_wep_key_len)) {
386 printf("Could not set individual WEP encryption.\n");
394 static void ieee802_1x_encapsulate_radius(hostapd *hapd, struct sta_info *sta,
397 struct radius_msg *msg;
399 struct eapol_state_machine *sm = sta->eapol_sm;
404 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
405 "Encapsulating EAP message into a RADIUS packet\n");
407 sm->radius_identifier = radius_client_get_id(hapd->radius);
408 msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST,
409 sm->radius_identifier);
411 printf("Could not create net RADIUS packet\n");
415 radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta));
418 !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME,
419 sm->identity, sm->identity_len)) {
420 printf("Could not add User-Name\n");
424 if (hapd->conf->own_ip_addr.af == AF_INET &&
425 !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
426 (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
427 printf("Could not add NAS-IP-Address\n");
432 if (hapd->conf->own_ip_addr.af == AF_INET6 &&
433 !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
434 (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
435 printf("Could not add NAS-IPv6-Address\n");
438 #endif /* CONFIG_IPV6 */
440 if (hapd->conf->nas_identifier &&
441 !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
442 (u8 *) hapd->conf->nas_identifier,
443 strlen(hapd->conf->nas_identifier))) {
444 printf("Could not add NAS-Identifier\n");
448 if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) {
449 printf("Could not add NAS-Port\n");
453 snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
454 MAC2STR(hapd->own_addr), hapd->conf->ssid);
455 if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
456 (u8 *) buf, strlen(buf))) {
457 printf("Could not add Called-Station-Id\n");
461 snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
463 if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
464 (u8 *) buf, strlen(buf))) {
465 printf("Could not add Calling-Station-Id\n");
469 /* TODO: should probably check MTU from driver config; 2304 is max for
470 * IEEE 802.11, but use 1400 to avoid problems with too large packets
472 if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) {
473 printf("Could not add Framed-MTU\n");
477 if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
478 RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
479 printf("Could not add NAS-Port-Type\n");
483 snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b");
484 if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
485 (u8 *) buf, strlen(buf))) {
486 printf("Could not add Connect-Info\n");
490 if (eap && !radius_msg_add_eap(msg, eap, len)) {
491 printf("Could not add EAP-Message\n");
495 /* State attribute must be copied if and only if this packet is
496 * Access-Request reply to the previous Access-Challenge */
497 if (sm->last_recv_radius && sm->last_recv_radius->hdr->code ==
498 RADIUS_CODE_ACCESS_CHALLENGE) {
499 int res = radius_msg_copy_attr(msg, sm->last_recv_radius,
502 printf("Could not copy State attribute from previous "
503 "Access-Challenge\n");
507 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
508 " Copied RADIUS State Attribute\n");
512 radius_client_send(hapd->radius, msg, RADIUS_AUTH, sta->addr);
516 radius_msg_free(msg);
521 static char *eap_type_text(u8 type)
524 case EAP_TYPE_IDENTITY: return "Identity";
525 case EAP_TYPE_NOTIFICATION: return "Notification";
526 case EAP_TYPE_NAK: return "Nak";
527 case EAP_TYPE_MD5: return "MD5-Challenge";
528 case EAP_TYPE_OTP: return "One-Time Password";
529 case EAP_TYPE_GTC: return "Generic Token Card";
530 case EAP_TYPE_TLS: return "TLS";
531 case EAP_TYPE_TTLS: return "TTLS";
532 case EAP_TYPE_PEAP: return "PEAP";
533 default: return "Unknown";
538 static void handle_eap_response(hostapd *hapd, struct sta_info *sta,
539 struct eap_hdr *eap, u8 *data, size_t len)
542 struct eapol_state_machine *sm = sta->eapol_sm;
546 if (eap->identifier != sm->currentId) {
547 hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
549 "EAP Identifier of the Response-Identity does "
550 "not match (was %d, expected %d) - ignored",
551 eap->identifier, sm->currentId);
556 printf("handle_eap_response: too short response data\n");
560 eloop_cancel_timeout(ieee802_1x_eap_timeout, sta, NULL);
562 free(sm->last_eap_supp);
563 sm->last_eap_supp_len = sizeof(*eap) + len;
564 sm->last_eap_supp = (u8 *) malloc(sm->last_eap_supp_len);
565 if (sm->last_eap_supp == NULL) {
566 printf("Could not alloc memory for last EAP Response\n");
569 memcpy(sm->last_eap_supp, eap, sizeof(*eap));
570 memcpy(sm->last_eap_supp + sizeof(*eap), data, len);
576 hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
577 HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d "
578 "id=%d len=%d) from STA: EAP Response-%s (%d)",
579 eap->code, eap->identifier, ntohs(eap->length),
580 eap_type_text(type), type);
582 if (type == EAP_TYPE_IDENTITY) {
585 buf = malloc(4 * len + 1);
588 for (i = 0; i < len; i++) {
589 if (data[i] >= 32 && data[i] < 127)
592 snprintf(pos, 5, "{%02x}", data[i]);
597 hostapd_logger(hapd, sm->addr,
598 HOSTAPD_MODULE_IEEE8021X,
600 "STA identity '%s'", buf);
604 sm->rx_identity = TRUE;
605 sm->dot1xAuthEapolRespIdFramesRx++;
607 /* Save station identity for future RADIUS packets */
609 sm->identity = malloc(len + 1);
611 memcpy(sm->identity, data, len);
612 sm->identity[len] = '\0';
613 sm->identity_len = len;
616 sm->dot1xAuthEapolRespFramesRx++;
622 /* Process incoming EAP packet from Supplicant */
623 static void handle_eap(hostapd *hapd, struct sta_info *sta, u8 *buf,
629 if (len < sizeof(*eap)) {
630 printf(" too short EAP packet\n");
634 eap = (struct eap_hdr *) buf;
636 eap_len = ntohs(eap->length);
637 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
638 " EAP: code=%d identifier=%d length=%d",
639 eap->code, eap->identifier, eap_len);
640 if (eap_len < sizeof(*eap)) {
641 printf(" Invalid EAP length\n");
643 } else if (eap_len > len) {
644 printf(" Too short frame to contain this EAP packet\n");
646 } else if (eap_len < len) {
647 printf(" Ignoring %lu extra bytes after EAP packet\n",
648 (unsigned long) len - eap_len);
651 eap_len -= sizeof(*eap);
654 case EAP_CODE_REQUEST:
655 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (request)\n");
657 case EAP_CODE_RESPONSE:
658 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (response)\n");
659 handle_eap_response(hapd, sta, eap, (u8 *) (eap + 1), eap_len);
661 case EAP_CODE_SUCCESS:
662 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (success)\n");
664 case EAP_CODE_FAILURE:
665 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (failure)\n");
668 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (unknown code)\n");
674 /* Process the EAPOL frames from the Supplicant */
675 void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
678 struct sta_info *sta;
679 struct ieee802_1x_hdr *hdr;
680 struct ieee802_1x_eapol_key *key;
683 if (!hapd->conf->ieee802_1x && !hapd->conf->wpa)
686 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
687 "IEEE 802.1X: %lu bytes from " MACSTR "\n",
688 (unsigned long) len, MAC2STR(sa));
689 sta = ap_get_sta(hapd, sa);
691 printf(" no station information available\n");
695 if (len < sizeof(*hdr)) {
696 printf(" too short IEEE 802.1X packet\n");
700 hdr = (struct ieee802_1x_hdr *) buf;
701 datalen = ntohs(hdr->length);
702 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
703 " IEEE 802.1X: version=%d type=%d length=%d\n",
704 hdr->version, hdr->type, datalen);
706 if (len - sizeof(*hdr) < datalen) {
707 printf(" frame too short for this IEEE 802.1X packet\n");
709 sta->eapol_sm->dot1xAuthEapLengthErrorFramesRx++;
712 if (len - sizeof(*hdr) > datalen) {
713 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
714 " ignoring %lu extra octets after IEEE 802.1X "
716 (unsigned long) len - sizeof(*hdr) - datalen);
720 sta->eapol_sm->dot1xAuthLastEapolFrameVersion = hdr->version;
721 sta->eapol_sm->dot1xAuthEapolFramesRx++;
724 key = (struct ieee802_1x_eapol_key *) (hdr + 1);
725 if (datalen >= sizeof(struct ieee802_1x_eapol_key) &&
726 hdr->type == IEEE802_1X_TYPE_EAPOL_KEY &&
727 (key->type == EAPOL_KEY_TYPE_WPA ||
728 key->type == EAPOL_KEY_TYPE_RSN)) {
729 wpa_receive(hapd, sta, (u8 *) hdr, sizeof(*hdr) + datalen);
733 if (!hapd->conf->ieee802_1x || sta->wpa_key_mgmt == WPA_KEY_MGMT_PSK)
736 if (!sta->eapol_sm) {
737 sta->eapol_sm = eapol_sm_alloc(hapd, sta);
742 /* since we support version 1, we can ignore version field and proceed
743 * as specified in version 1 standard [IEEE Std 802.1X-2001, 7.5.5] */
744 /* TODO: actually, we are not version 1 anymore.. However, Version 2
745 * does not change frame contents, so should be ok to process frames
746 * more or less identically. Some changes might be needed for
747 * verification of fields. */
750 case IEEE802_1X_TYPE_EAP_PACKET:
751 handle_eap(hapd, sta, (u8 *) (hdr + 1), datalen);
754 case IEEE802_1X_TYPE_EAPOL_START:
755 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
756 HOSTAPD_LEVEL_DEBUG, "received EAPOL-Start "
759 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
760 HOSTAPD_LEVEL_DEBUG, "cached PMKSA "
761 "available - ignore it since "
762 "STA sent EAPOL-Start");
765 sta->eapol_sm->auth_pae.eapolStart = TRUE;
766 sta->eapol_sm->dot1xAuthEapolStartFramesRx++;
767 wpa_sm_event(hapd, sta, WPA_REAUTH_EAPOL);
770 case IEEE802_1X_TYPE_EAPOL_LOGOFF:
771 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
772 HOSTAPD_LEVEL_DEBUG, "received EAPOL-Logoff "
774 sta->acct_terminate_cause =
775 RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
776 sta->eapol_sm->auth_pae.eapolLogoff = TRUE;
777 sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++;
780 case IEEE802_1X_TYPE_EAPOL_KEY:
781 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " EAPOL-Key\n");
782 if (!(sta->flags & WLAN_STA_AUTHORIZED)) {
783 printf(" Dropped key data from unauthorized "
789 case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT:
790 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
791 " EAPOL-Encapsulated-ASF-Alert\n");
792 /* TODO: implement support for this; show data */
796 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
797 " unknown IEEE 802.1X packet type\n");
798 sta->eapol_sm->dot1xAuthInvalidEapolFramesRx++;
802 eapol_sm_step(sta->eapol_sm);
806 void ieee802_1x_new_station(hostapd *hapd, struct sta_info *sta)
808 if (!hapd->conf->ieee802_1x || sta->wpa_key_mgmt == WPA_KEY_MGMT_PSK)
811 if (sta->eapol_sm == NULL) {
812 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
813 HOSTAPD_LEVEL_DEBUG, "start authentication");
814 sta->eapol_sm = eapol_sm_alloc(hapd, sta);
815 if (sta->eapol_sm == NULL) {
816 hostapd_logger(hapd, sta->addr,
817 HOSTAPD_MODULE_IEEE8021X,
819 "failed to allocate state machine");
824 sta->eapol_sm->portEnabled = TRUE;
827 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
829 "PMK from PMKSA cache - skip IEEE 802.1X/EAP");
830 /* Setup EAPOL state machines to already authenticated state
831 * because of existing PMKSA information in the cache. */
832 sta->eapol_sm->keyRun = TRUE;
833 sta->eapol_sm->keyAvailable = TRUE;
834 sta->eapol_sm->auth_pae.state = AUTH_PAE_AUTHENTICATING;
835 sta->eapol_sm->be_auth.state = BE_AUTH_SUCCESS;
836 sta->eapol_sm->authSuccess = TRUE;
837 if (sta->eapol_sm->eap)
838 eap_sm_notify_cached(sta->eapol_sm->eap);
840 eapol_sm_step(sta->eapol_sm);
844 void ieee802_1x_free_radius_class(struct radius_class_data *class)
849 for (i = 0; i < class->count; i++)
850 free(class->attr[i].data);
857 int ieee802_1x_copy_radius_class(struct radius_class_data *dst,
858 struct radius_class_data *src)
862 if (src->attr == NULL)
865 dst->attr = malloc(src->count * sizeof(struct radius_attr_data));
866 if (dst->attr == NULL)
869 memset(dst->attr, 0, src->count * sizeof(struct radius_attr_data));
872 for (i = 0; i < src->count; i++) {
873 dst->attr[i].data = malloc(src->attr[i].len);
874 if (dst->attr[i].data == NULL)
877 memcpy(dst->attr[i].data, src->attr[i].data, src->attr[i].len);
878 dst->attr[i].len = src->attr[i].len;
885 void ieee802_1x_free_station(struct sta_info *sta)
887 struct eapol_state_machine *sm = sta->eapol_sm;
889 eloop_cancel_timeout(ieee802_1x_eap_timeout, sta, NULL);
894 sta->eapol_sm = NULL;
896 if (sm->last_recv_radius) {
897 radius_msg_free(sm->last_recv_radius);
898 free(sm->last_recv_radius);
901 free(sm->last_eap_supp);
902 free(sm->last_eap_radius);
904 ieee802_1x_free_radius_class(&sm->radius_class);
905 free(sm->eapol_key_sign);
906 free(sm->eapol_key_crypt);
911 static void ieee802_1x_decapsulate_radius(hostapd *hapd, struct sta_info *sta)
918 struct radius_msg *msg;
919 struct eapol_state_machine *sm = sta->eapol_sm;
921 if (sm == NULL || sm->last_recv_radius == NULL) {
923 sm->be_auth.eapNoReq = TRUE;
927 msg = sm->last_recv_radius;
929 eap = radius_msg_get_eap(msg, &len);
931 /* draft-aboba-radius-rfc2869bis-20.txt, Chap. 2.6.3:
932 * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message
934 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
935 HOSTAPD_LEVEL_WARNING, "could not extract "
936 "EAP-Message from RADIUS message");
937 free(sm->last_eap_radius);
938 sm->last_eap_radius = NULL;
939 sm->last_eap_radius_len = 0;
940 sm->be_auth.eapNoReq = TRUE;
944 if (len < sizeof(*hdr)) {
945 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
946 HOSTAPD_LEVEL_WARNING, "too short EAP packet "
947 "received from authentication server");
949 sm->be_auth.eapNoReq = TRUE;
953 if (len > sizeof(*hdr))
954 eap_type = eap[sizeof(*hdr)];
956 hdr = (struct eap_hdr *) eap;
958 case EAP_CODE_REQUEST:
959 snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)",
960 eap_type >= 0 ? eap_type_text(eap_type) : "??",
963 case EAP_CODE_RESPONSE:
964 snprintf(buf, sizeof(buf), "EAP Response-%s (%d)",
965 eap_type >= 0 ? eap_type_text(eap_type) : "??",
968 case EAP_CODE_SUCCESS:
969 snprintf(buf, sizeof(buf), "EAP Success");
971 case EAP_CODE_FAILURE:
972 snprintf(buf, sizeof(buf), "EAP Failure");
975 snprintf(buf, sizeof(buf), "unknown EAP code");
978 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
979 HOSTAPD_LEVEL_DEBUG, "decapsulated EAP packet (code=%d "
980 "id=%d len=%d) from RADIUS server: %s",
981 hdr->code, hdr->identifier, ntohs(hdr->length), buf);
982 sm->be_auth.eapReq = TRUE;
984 free(sm->last_eap_radius);
985 sm->last_eap_radius = eap;
986 sm->last_eap_radius_len = len;
990 static void ieee802_1x_get_keys(hostapd *hapd, struct sta_info *sta,
991 struct radius_msg *msg, struct radius_msg *req,
992 u8 *shared_secret, size_t shared_secret_len)
994 struct radius_ms_mppe_keys *keys;
995 struct eapol_state_machine *sm = sta->eapol_sm;
999 keys = radius_msg_get_ms_keys(msg, req, shared_secret,
1003 if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL) && keys->send) {
1005 printf("MS-MPPE-Send-Key (len=%lu):",
1006 (unsigned long) keys->send_len);
1007 for (i = 0; i < keys->send_len; i++)
1008 printf(" %02x", keys->send[i]);
1011 if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL) && keys->recv) {
1013 printf("MS-MPPE-Recv-Key (len=%lu):",
1014 (unsigned long) keys->recv_len);
1015 for (i = 0; i < keys->recv_len; i++)
1016 printf(" %02x", keys->recv[i]);
1020 if (keys->send && keys->recv) {
1021 free(sm->eapol_key_sign);
1022 free(sm->eapol_key_crypt);
1023 sm->eapol_key_sign = keys->send;
1024 sm->eapol_key_sign_len = keys->send_len;
1025 sm->eapol_key_crypt = keys->recv;
1026 sm->eapol_key_crypt_len = keys->recv_len;
1027 if (hapd->default_wep_key ||
1028 hapd->conf->individual_wep_key_len > 0 ||
1030 sta->eapol_sm->keyAvailable = TRUE;
1040 static void ieee802_1x_store_radius_class(struct hostapd_data *hapd,
1041 struct sta_info *sta,
1042 struct radius_msg *msg)
1046 struct eapol_state_machine *sm = sta->eapol_sm;
1048 struct radius_attr_data *nclass;
1049 size_t nclass_count;
1051 if (!hapd->conf->radius->acct_server || hapd->radius == NULL ||
1055 ieee802_1x_free_radius_class(&sm->radius_class);
1056 count = radius_msg_count_attr(msg, RADIUS_ATTR_CLASS, 1);
1060 nclass = malloc(count * sizeof(struct radius_attr_data));
1065 memset(nclass, 0, count * sizeof(struct radius_attr_data));
1068 for (i = 0; i < count; i++) {
1070 if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CLASS,
1076 } while (class_len < 1);
1078 nclass[nclass_count].data = malloc(class_len);
1079 if (nclass[nclass_count].data == NULL)
1082 memcpy(nclass[nclass_count].data, class, class_len);
1083 nclass[nclass_count].len = class_len;
1087 sm->radius_class.attr = nclass;
1088 sm->radius_class.count = nclass_count;
1089 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "IEEE 802.1X: Stored %lu RADIUS "
1090 "Class attributes for " MACSTR "\n",
1091 (unsigned long) sm->radius_class.count,
1092 MAC2STR(sta->addr));
1096 /* Update sta->identity based on User-Name attribute in Access-Accept */
1097 static void ieee802_1x_update_sta_identity(struct hostapd_data *hapd,
1098 struct sta_info *sta,
1099 struct radius_msg *msg)
1103 struct eapol_state_machine *sm = sta->eapol_sm;
1108 if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, &buf, &len,
1112 identity = malloc(len + 1);
1113 if (identity == NULL)
1116 memcpy(identity, buf, len);
1117 identity[len] = '\0';
1119 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
1120 HOSTAPD_LEVEL_DEBUG, "old identity '%s' updated with "
1121 "User-Name from Access-Accept '%s'",
1122 sm->identity ? (char *) sm->identity : "N/A",
1126 sm->identity = identity;
1127 sm->identity_len = len;
1131 struct sta_id_search {
1133 struct eapol_state_machine *sm;
1137 static int ieee802_1x_select_radius_identifier(struct hostapd_data *hapd,
1138 struct sta_info *sta,
1141 struct sta_id_search *id_search = ctx;
1142 struct eapol_state_machine *sm = sta->eapol_sm;
1144 if (sm && sm->radius_identifier >= 0 &&
1145 sm->radius_identifier == id_search->identifier) {
1153 static struct eapol_state_machine *
1154 ieee802_1x_search_radius_identifier(struct hostapd_data *hapd, u8 identifier)
1156 struct sta_id_search id_search;
1157 id_search.identifier = identifier;
1158 id_search.sm = NULL;
1159 ap_for_each_sta(hapd, ieee802_1x_select_radius_identifier, &id_search);
1160 return id_search.sm;
1164 /* Process the RADIUS frames from Authentication Server */
1165 static RadiusRxResult
1166 ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
1167 u8 *shared_secret, size_t shared_secret_len,
1170 struct hostapd_data *hapd = data;
1171 struct sta_info *sta;
1172 u32 session_timeout = 0, termination_action, acct_interim_interval;
1173 int session_timeout_set;
1175 struct eapol_state_machine *sm;
1176 int override_eapReq = 0;
1178 sm = ieee802_1x_search_radius_identifier(hapd, msg->hdr->identifier);
1180 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "IEEE 802.1X: Could not "
1181 "find matching station for this RADIUS "
1183 return RADIUS_RX_UNKNOWN;
1187 /* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be
1188 * present when packet contains an EAP-Message attribute */
1189 if (msg->hdr->code == RADIUS_CODE_ACCESS_REJECT &&
1190 radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL,
1192 radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) {
1193 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Allowing RADIUS "
1194 "Access-Reject without Message-Authenticator "
1195 "since it does not include EAP-Message\n");
1196 } else if (radius_msg_verify(msg, shared_secret, shared_secret_len,
1198 printf("Incoming RADIUS packet did not have correct "
1199 "Message-Authenticator - dropped\n");
1200 return RADIUS_RX_INVALID_AUTHENTICATOR;
1203 if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
1204 msg->hdr->code != RADIUS_CODE_ACCESS_REJECT &&
1205 msg->hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) {
1206 printf("Unknown RADIUS message code\n");
1207 return RADIUS_RX_UNKNOWN;
1210 sm->radius_identifier = -1;
1211 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
1212 "RADIUS packet matching with station " MACSTR "\n",
1213 MAC2STR(sta->addr));
1215 if (sm->last_recv_radius) {
1216 radius_msg_free(sm->last_recv_radius);
1217 free(sm->last_recv_radius);
1220 sm->last_recv_radius = msg;
1222 session_timeout_set =
1223 !radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
1225 if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_TERMINATION_ACTION,
1226 &termination_action))
1227 termination_action = RADIUS_TERMINATION_ACTION_DEFAULT;
1229 if (hapd->conf->radius->acct_interim_interval == 0 &&
1230 msg->hdr->code == RADIUS_CODE_ACCESS_ACCEPT &&
1231 radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL,
1232 &acct_interim_interval) == 0) {
1233 if (acct_interim_interval < 60) {
1234 hostapd_logger(hapd, sta->addr,
1235 HOSTAPD_MODULE_IEEE8021X,
1237 "ignored too small "
1238 "Acct-Interim-Interval %d",
1239 acct_interim_interval);
1241 sta->acct_interim_interval = acct_interim_interval;
1245 switch (msg->hdr->code) {
1246 case RADIUS_CODE_ACCESS_ACCEPT:
1247 /* RFC 3580, Ch. 3.17 */
1248 if (session_timeout_set && termination_action ==
1249 RADIUS_TERMINATION_ACTION_RADIUS_REQUEST) {
1250 sm->reauth_timer.reAuthPeriod = session_timeout;
1251 } else if (session_timeout_set)
1252 ap_sta_session_timeout(hapd, sta, session_timeout);
1254 sm->eapSuccess = TRUE;
1255 override_eapReq = 1;
1256 ieee802_1x_get_keys(hapd, sta, msg, req, shared_secret,
1258 ieee802_1x_store_radius_class(hapd, sta, msg);
1259 ieee802_1x_update_sta_identity(hapd, sta, msg);
1260 if (sm->keyAvailable) {
1261 pmksa_cache_add(hapd, sta, sm->eapol_key_crypt,
1262 session_timeout_set ?
1263 session_timeout : -1);
1266 case RADIUS_CODE_ACCESS_REJECT:
1268 override_eapReq = 1;
1270 case RADIUS_CODE_ACCESS_CHALLENGE:
1271 if (session_timeout_set) {
1272 /* RFC 2869, Ch. 2.3.2; RFC 3580, Ch. 3.17 */
1273 eap_timeout = session_timeout;
1276 hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
1277 HOSTAPD_LEVEL_DEBUG,
1278 "using EAP timeout of %d seconds%s",
1280 session_timeout_set ? " (from RADIUS)" : "");
1281 eloop_cancel_timeout(ieee802_1x_eap_timeout, sta, NULL);
1282 eloop_register_timeout(eap_timeout, 0, ieee802_1x_eap_timeout,
1284 sm->eapTimeout = FALSE;
1288 ieee802_1x_decapsulate_radius(hapd, sta);
1289 if (override_eapReq)
1290 sm->be_auth.eapReq = FALSE;
1294 return RADIUS_RX_QUEUED;
1298 /* Handler for EAPOL Backend Authentication state machine sendRespToServer.
1299 * Forward the EAP Response from Supplicant to Authentication Server. */
1300 void ieee802_1x_send_resp_to_server(hostapd *hapd, struct sta_info *sta)
1302 struct eapol_state_machine *sm = sta->eapol_sm;
1306 if (hapd->conf->eap_server) {
1307 eap_set_eapRespData(sm->eap, sm->last_eap_supp,
1308 sm->last_eap_supp_len);
1310 ieee802_1x_encapsulate_radius(hapd, sta, sm->last_eap_supp,
1311 sm->last_eap_supp_len);
1316 void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta)
1318 struct eapol_state_machine *sm = sta->eapol_sm;
1322 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
1323 HOSTAPD_LEVEL_DEBUG, "aborting authentication");
1325 if (sm->last_recv_radius) {
1326 radius_msg_free(sm->last_recv_radius);
1327 free(sm->last_recv_radius);
1328 sm->last_recv_radius = NULL;
1330 free(sm->last_eap_supp);
1331 sm->last_eap_supp = NULL;
1332 sm->last_eap_supp_len = 0;
1333 free(sm->last_eap_radius);
1334 sm->last_eap_radius = NULL;
1335 sm->last_eap_radius_len = 0;
1339 void ieee802_1x_set_port_enabled(hostapd *hapd, struct sta_info *sta,
1345 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
1346 "IEEE 802.1X: station " MACSTR " port %s\n",
1347 MAC2STR(sta->addr), enabled ? "enabled" : "disabled");
1348 sta->eapol_sm->portEnabled = enabled ? TRUE : FALSE;
1349 eapol_sm_step(sta->eapol_sm);
1353 #ifdef HOSTAPD_DUMP_STATE
1354 void ieee802_1x_dump_state(FILE *f, const char *prefix, struct sta_info *sta)
1356 struct eapol_state_machine *sm = sta->eapol_sm;
1360 fprintf(f, "%sIEEE 802.1X:\n", prefix);
1364 fprintf(f, "%sidentity=", prefix);
1365 for (i = 0; i < sm->identity_len; i++)
1366 fprint_char(f, sm->identity[i]);
1370 fprintf(f, "%scached_packets=%s%s%s\n", prefix,
1371 sm->last_recv_radius ? "[RX RADIUS]" : "",
1372 sm->last_eap_radius ? "[EAP RADIUS]" : "",
1373 sm->last_eap_supp ? "[EAP SUPPLICANT]" : "");
1375 eapol_sm_dump_state(f, prefix, sm);
1377 #endif /* HOSTAPD_DUMP_STATE */
1380 static int ieee802_1x_rekey_broadcast(hostapd *hapd)
1382 if (hapd->conf->default_wep_key_len < 1)
1385 free(hapd->default_wep_key);
1386 hapd->default_wep_key = malloc(hapd->conf->default_wep_key_len);
1387 if (hapd->default_wep_key == NULL ||
1388 hostapd_get_rand(hapd->default_wep_key,
1389 hapd->conf->default_wep_key_len)) {
1390 printf("Could not generate random WEP key.\n");
1391 free(hapd->default_wep_key);
1392 hapd->default_wep_key = NULL;
1396 if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) {
1397 hostapd_hexdump("IEEE 802.1X: New default WEP key",
1398 hapd->default_wep_key,
1399 hapd->conf->default_wep_key_len);
1406 static int ieee802_1x_sta_key_available(struct hostapd_data *hapd,
1407 struct sta_info *sta, void *ctx)
1409 if (sta->eapol_sm) {
1410 sta->eapol_sm->keyAvailable = TRUE;
1411 eapol_sm_step(sta->eapol_sm);
1417 static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
1419 struct hostapd_data *hapd = eloop_ctx;
1421 if (hapd->default_wep_key_idx >= 3)
1422 hapd->default_wep_key_idx =
1423 hapd->conf->individual_wep_key_len > 0 ? 1 : 0;
1425 hapd->default_wep_key_idx++;
1427 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "IEEE 802.1X: New default WEP "
1428 "key index %d\n", hapd->default_wep_key_idx);
1430 if (ieee802_1x_rekey_broadcast(hapd)) {
1431 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
1432 HOSTAPD_LEVEL_WARNING, "failed to generate a "
1433 "new broadcast key");
1434 free(hapd->default_wep_key);
1435 hapd->default_wep_key = NULL;
1439 /* TODO: Could setup key for RX here, but change default TX keyid only
1440 * after new broadcast key has been sent to all stations. */
1441 if (hostapd_set_encryption(hapd, "WEP", NULL,
1442 hapd->default_wep_key_idx,
1443 hapd->default_wep_key,
1444 hapd->conf->default_wep_key_len)) {
1445 hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
1446 HOSTAPD_LEVEL_WARNING, "failed to configure a "
1447 "new broadcast key");
1448 free(hapd->default_wep_key);
1449 hapd->default_wep_key = NULL;
1453 ap_for_each_sta(hapd, ieee802_1x_sta_key_available, NULL);
1455 if (hapd->conf->wep_rekeying_period > 0) {
1456 eloop_register_timeout(hapd->conf->wep_rekeying_period, 0,
1457 ieee802_1x_rekey, hapd, NULL);
1462 int ieee802_1x_init(hostapd *hapd)
1466 if ((hapd->conf->ieee802_1x || hapd->conf->wpa) &&
1467 hostapd_set_ieee8021x(hapd, 1))
1470 if (radius_client_register(hapd->radius, RADIUS_AUTH,
1471 ieee802_1x_receive_auth, hapd))
1474 if (hapd->conf->default_wep_key_len) {
1475 for (i = 0; i < 4; i++)
1476 hostapd_set_encryption(hapd, "none", NULL, i, NULL, 0);
1478 ieee802_1x_rekey(hapd, NULL);
1480 if (hapd->default_wep_key == NULL)
1488 void ieee802_1x_deinit(hostapd *hapd)
1490 if (hapd->driver != NULL &&
1491 (hapd->conf->ieee802_1x || hapd->conf->wpa))
1492 hostapd_set_ieee8021x(hapd, 0);
1496 static void ieee802_1x_new_auth_session(struct hostapd_data *hapd,
1497 struct sta_info *sta)
1499 struct eapol_state_machine *sm = sta->eapol_sm;
1503 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
1504 "IEEE 802.1X: station " MACSTR " - new auth session, "
1505 "clearing State\n", MAC2STR(sta->addr));
1507 if (sm->last_recv_radius) {
1508 radius_msg_free(sm->last_recv_radius);
1509 free(sm->last_recv_radius);
1510 sm->last_recv_radius = NULL;
1513 sm->eapSuccess = FALSE;
1514 sm->eapFail = FALSE;
1518 int ieee802_1x_tx_status(hostapd *hapd, struct sta_info *sta, u8 *buf,
1519 size_t len, int ack)
1521 struct ieee80211_hdr *hdr;
1522 struct ieee802_1x_hdr *xhdr;
1523 struct ieee802_1x_eapol_key *key;
1528 if (len < sizeof(*hdr) + sizeof(rfc1042_header) + 2 + sizeof(*xhdr))
1531 hdr = (struct ieee80211_hdr *) buf;
1532 pos = (u8 *) (hdr + 1);
1533 if (memcmp(pos, rfc1042_header, sizeof(rfc1042_header)) != 0)
1535 pos += sizeof(rfc1042_header);
1536 if (((pos[0] << 8) | pos[1]) != ETH_P_PAE)
1540 xhdr = (struct ieee802_1x_hdr *) pos;
1541 pos += sizeof(*xhdr);
1543 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "IEEE 802.1X: " MACSTR
1544 " TX status - version=%d type=%d length=%d - ack=%d\n",
1545 MAC2STR(sta->addr), xhdr->version, xhdr->type,
1546 ntohs(xhdr->length), ack);
1548 /* EAPOL EAP-Packet packets are eventually re-sent by either Supplicant
1549 * or Authenticator state machines, but EAPOL-Key packets are not
1550 * retransmitted in case of failure. Try to re-sent failed EAPOL-Key
1551 * packets couple of times because otherwise STA keys become
1552 * unsynchronized with AP. */
1553 if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY && !ack &&
1554 pos + sizeof(*key) <= buf + len) {
1555 key = (struct ieee802_1x_eapol_key *) pos;
1556 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
1557 HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key "
1558 "frame (%scast index=%d)",
1559 key->key_index & BIT(7) ? "uni" : "broad",
1560 key->key_index & ~BIT(7));
1561 /* TODO: re-send EAPOL-Key couple of times (with short delay
1562 * between them?). If all attempt fail, report error and
1563 * deauthenticate STA so that it will get new keys when
1564 * authenticating again (e.g., after returning in range).
1565 * Separate limit/transmit state needed both for unicast and
1566 * broadcast keys(?) */
1568 /* TODO: could move unicast key configuration from ieee802_1x_tx_key()
1569 * to here and change the key only if the EAPOL-Key packet was Acked.
1576 u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len)
1578 if (sm == NULL || sm->identity == NULL)
1581 *len = sm->identity_len;
1582 return sm->identity;
1586 u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
1589 if (sm == NULL || sm->radius_class.attr == NULL ||
1590 idx >= sm->radius_class.count)
1593 *len = sm->radius_class.attr[idx].len;
1594 return sm->radius_class.attr[idx].data;
1598 u8 * ieee802_1x_get_key_crypt(struct eapol_state_machine *sm, size_t *len)
1603 *len = sm->eapol_key_crypt_len;
1604 return sm->eapol_key_crypt;
1608 void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm,
1613 sm->portEnabled = enabled ? TRUE : FALSE;
1618 void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm,
1623 sm->portValid = valid ? TRUE : FALSE;
1628 void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth)
1633 sm->flags |= EAPOL_SM_PREAUTH;
1635 sm->flags &= ~EAPOL_SM_PREAUTH;
1639 static const char * bool_txt(Boolean bool)
1641 return bool ? "TRUE" : "FALSE";
1645 int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
1652 int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
1653 char *buf, size_t buflen)
1656 struct eapol_state_machine *sm = sta->eapol_sm;
1661 len += snprintf(buf + len, buflen - len,
1662 "dot1xPaePortNumber=%d\n"
1663 "dot1xPaePortProtocolVersion=%d\n"
1664 "dot1xPaePortCapabilities=1\n"
1665 "dot1xPaePortInitialize=%d\n"
1666 "dot1xPaePortReauthenticate=FALSE\n",
1671 /* dot1xAuthConfigTable */
1672 len += snprintf(buf + len, buflen - len,
1673 "dot1xAuthPaeState=%d\n"
1674 "dot1xAuthBackendAuthState=%d\n"
1675 "dot1xAuthAdminControlledDirections=%d\n"
1676 "dot1xAuthOperControlledDirections=%d\n"
1677 "dot1xAuthAuthControlledPortStatus=%d\n"
1678 "dot1xAuthAuthControlledPortControl=%d\n"
1679 "dot1xAuthQuietPeriod=%u\n"
1680 "dot1xAuthServerTimeout=%u\n"
1681 "dot1xAuthReAuthPeriod=%u\n"
1682 "dot1xAuthReAuthEnabled=%s\n"
1683 "dot1xAuthKeyTxEnabled=%s\n",
1684 sm->auth_pae.state + 1,
1685 sm->be_auth.state + 1,
1686 sm->ctrl_dir.adminControlledDirections,
1687 sm->ctrl_dir.operControlledDirections,
1690 sm->auth_pae.quietPeriod,
1691 sm->be_auth.serverTimeout,
1692 sm->reauth_timer.reAuthPeriod,
1693 bool_txt(sm->reauth_timer.reAuthEnabled),
1694 bool_txt(sm->keyTxEnabled));
1696 /* dot1xAuthStatsTable */
1697 len += snprintf(buf + len, buflen - len,
1698 "dot1xAuthEapolFramesRx=%u\n"
1699 "dot1xAuthEapolFramesTx=%u\n"
1700 "dot1xAuthEapolStartFramesRx=%u\n"
1701 "dot1xAuthEapolLogoffFramesRx=%u\n"
1702 "dot1xAuthEapolRespIdFramesRx=%u\n"
1703 "dot1xAuthEapolRespFramesRx=%u\n"
1704 "dot1xAuthEapolReqIdFramesTx=%u\n"
1705 "dot1xAuthEapolReqFramesTx=%u\n"
1706 "dot1xAuthInvalidEapolFramesRx=%u\n"
1707 "dot1xAuthEapLengthErrorFramesRx=%u\n"
1708 "dot1xAuthLastEapolFrameVersion=%u\n"
1709 "dot1xAuthLastEapolFrameSource=" MACSTR "\n",
1710 sm->dot1xAuthEapolFramesRx,
1711 sm->dot1xAuthEapolFramesTx,
1712 sm->dot1xAuthEapolStartFramesRx,
1713 sm->dot1xAuthEapolLogoffFramesRx,
1714 sm->dot1xAuthEapolRespIdFramesRx,
1715 sm->dot1xAuthEapolRespFramesRx,
1716 sm->dot1xAuthEapolReqIdFramesTx,
1717 sm->dot1xAuthEapolReqFramesTx,
1718 sm->dot1xAuthInvalidEapolFramesRx,
1719 sm->dot1xAuthEapLengthErrorFramesRx,
1720 sm->dot1xAuthLastEapolFrameVersion,
1723 /* dot1xAuthDiagTable */
1724 len += snprintf(buf + len, buflen - len,
1725 "dot1xAuthEntersConnecting=%u\n"
1726 "dot1xAuthEapLogoffsWhileConnecting=%u\n"
1727 "dot1xAuthEntersAuthenticating=%u\n"
1728 "dot1xAuthAuthSuccessesWhileAuthenticating=%u\n"
1729 "dot1xAuthAuthTimeoutsWhileAuthenticating=%u\n"
1730 "dot1xAuthAuthFailWhileAuthenticating=%u\n"
1731 "dot1xAuthAuthEapStartsWhileAuthenticating=%u\n"
1732 "dot1xAuthAuthEapLogoffWhileAuthenticating=%u\n"
1733 "dot1xAuthAuthReauthsWhileAuthenticated=%u\n"
1734 "dot1xAuthAuthEapStartsWhileAuthenticated=%u\n"
1735 "dot1xAuthAuthEapLogoffWhileAuthenticated=%u\n"
1736 "dot1xAuthBackendResponses=%u\n"
1737 "dot1xAuthBackendAccessChallenges=%u\n"
1738 "dot1xAuthBackendOtherRequestsToSupplicant=%u\n"
1739 "dot1xAuthBackendAuthSuccesses=%u\n"
1740 "dot1xAuthBackendAuthFails=%u\n",
1741 sm->auth_pae.authEntersConnecting,
1742 sm->auth_pae.authEapLogoffsWhileConnecting,
1743 sm->auth_pae.authEntersAuthenticating,
1744 sm->auth_pae.authAuthSuccessesWhileAuthenticating,
1745 sm->auth_pae.authAuthTimeoutsWhileAuthenticating,
1746 sm->auth_pae.authAuthFailWhileAuthenticating,
1747 sm->auth_pae.authAuthEapStartsWhileAuthenticating,
1748 sm->auth_pae.authAuthEapLogoffWhileAuthenticating,
1749 sm->auth_pae.authAuthReauthsWhileAuthenticated,
1750 sm->auth_pae.authAuthEapStartsWhileAuthenticated,
1751 sm->auth_pae.authAuthEapLogoffWhileAuthenticated,
1752 sm->be_auth.backendResponses,
1753 sm->be_auth.backendAccessChallenges,
1754 sm->be_auth.backendOtherRequestsToSupplicant,
1755 sm->be_auth.backendAuthSuccesses,
1756 sm->be_auth.backendAuthFails);
1758 /* dot1xAuthSessionStatsTable */
1759 len += snprintf(buf + len, buflen - len,
1760 /* TODO: dot1xAuthSessionOctetsRx */
1761 /* TODO: dot1xAuthSessionOctetsTx */
1762 /* TODO: dot1xAuthSessionFramesRx */
1763 /* TODO: dot1xAuthSessionFramesTx */
1764 "dot1xAuthSessionId=%08X-%08X\n"
1765 "dot1xAuthSessionAuthenticMethod=%d\n"
1766 "dot1xAuthSessionTime=%u\n"
1767 "dot1xAuthSessionTerminateCause=999\n"
1768 "dot1xAuthSessionUserName=%s\n",
1769 sta->acct_session_id_hi, sta->acct_session_id_lo,
1770 sta->wpa_key_mgmt == WPA_KEY_MGMT_IEEE8021X ? 1 : 2,
1771 (unsigned int) (time(NULL) - sta->acct_session_start),
1778 void ieee802_1x_finished(struct hostapd_data *hapd, struct sta_info *sta,
1783 /* TODO: get PMKLifetime from WPA parameters */
1784 static const int dot11RSNAConfigPMKLifetime = 43200;
1786 key = ieee802_1x_get_key_crypt(sta->eapol_sm, &len);
1787 if (success && key) {
1788 pmksa_cache_add(hapd, sta, key, dot11RSNAConfigPMKLifetime);