diff options
Diffstat (limited to 'src/ap/ieee802_1x.c')
-rw-r--r-- | src/ap/ieee802_1x.c | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c index 753c8833..46a47d06 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c @@ -998,7 +998,7 @@ ieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta) static void ieee802_1x_save_eapol(struct sta_info *sta, const u8 *buf, - size_t len) + size_t len, enum frame_encryption encrypted) { if (sta->pending_eapol_rx) { wpabuf_free(sta->pending_eapol_rx->buf); @@ -1016,21 +1016,39 @@ static void ieee802_1x_save_eapol(struct sta_info *sta, const u8 *buf, return; } + sta->pending_eapol_rx->encrypted = encrypted; os_get_reltime(&sta->pending_eapol_rx->rx_time); } +static bool ieee802_1x_check_encryption(struct sta_info *sta, + enum frame_encryption encrypted, + u8 type) +{ + if (encrypted != FRAME_NOT_ENCRYPTED) + return true; + if (type != IEEE802_1X_TYPE_EAP_PACKET && + type != IEEE802_1X_TYPE_EAPOL_START && + type != IEEE802_1X_TYPE_EAPOL_LOGOFF) + return true; + if (!(sta->flags & WLAN_STA_MFP)) + return true; + return !wpa_auth_pairwise_set(sta->wpa_sm); +} + + /** * ieee802_1x_receive - Process the EAPOL frames from the Supplicant * @hapd: hostapd BSS data * @sa: Source address (sender of the EAPOL frame) * @buf: EAPOL frame * @len: Length of buf in octets + * @encrypted: Whether the frame was encrypted * * This function is called for each incoming EAPOL frame from the interface */ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, - size_t len) + size_t len, enum frame_encryption encrypted) { struct sta_info *sta; struct ieee802_1x_hdr *hdr; @@ -1043,8 +1061,9 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, !hapd->conf->wps_state) return; - wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR, - (unsigned long) len, MAC2STR(sa)); + wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR + " (encrypted=%d)", + (unsigned long) len, MAC2STR(sa), encrypted); sta = ap_get_sta(hapd, sa); if (!sta || (!(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH)) && !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED))) { @@ -1054,7 +1073,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, if (sta && (sta->flags & WLAN_STA_AUTH)) { wpa_printf(MSG_DEBUG, "Saving EAPOL frame from " MACSTR " for later use", MAC2STR(sta->addr)); - ieee802_1x_save_eapol(sta, buf, len); + ieee802_1x_save_eapol(sta, buf, len, encrypted); } return; @@ -1114,6 +1133,12 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, return; } + if (!ieee802_1x_check_encryption(sta, encrypted, hdr->type)) { + wpa_printf(MSG_DEBUG, + "IEEE 802.1X: Discard unencrypted EAPOL message - encryption was expected"); + return; + } + if (!sta->eapol_sm) { sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta); if (!sta->eapol_sm) @@ -1684,23 +1709,35 @@ static void ieee802_1x_hs20_sub_rem(struct sta_info *sta, u8 *pos, size_t len) static void ieee802_1x_hs20_deauth_req(struct hostapd_data *hapd, - struct sta_info *sta, u8 *pos, + struct sta_info *sta, const u8 *pos, size_t len) { + size_t url_len; + unsigned int timeout; + if (len < 3) return; /* Malformed information */ + url_len = len - 3; sta->hs20_deauth_requested = 1; + sta->hs20_deauth_on_ack = url_len == 0; wpa_printf(MSG_DEBUG, - "HS 2.0: Deauthentication request - Code %u Re-auth Delay %u", - *pos, WPA_GET_LE16(pos + 1)); + "HS 2.0: Deauthentication request - Code %u Re-auth Delay %u URL length %zu", + *pos, WPA_GET_LE16(pos + 1), url_len); wpabuf_free(sta->hs20_deauth_req); sta->hs20_deauth_req = wpabuf_alloc(len + 1); if (sta->hs20_deauth_req) { wpabuf_put_data(sta->hs20_deauth_req, pos, 3); - wpabuf_put_u8(sta->hs20_deauth_req, len - 3); - wpabuf_put_data(sta->hs20_deauth_req, pos + 3, len - 3); + wpabuf_put_u8(sta->hs20_deauth_req, url_len); + wpabuf_put_data(sta->hs20_deauth_req, pos + 3, url_len); } - ap_sta_session_timeout(hapd, sta, hapd->conf->hs20_deauth_req_timeout); + timeout = hapd->conf->hs20_deauth_req_timeout; + /* If there is no URL, no need to provide time to fetch it. Use a short + * timeout here to allow maximum time for completing 4-way handshake and + * WNM-Notification delivery. Acknowledgement of the frame will result + * in cutting this wait further. */ + if (!url_len && timeout > 2) + timeout = 2; + ap_sta_session_timeout(hapd, sta, timeout); } @@ -1788,6 +1825,7 @@ static void ieee802_1x_check_hs20(struct hostapd_data *hapd, buf = NULL; sta->remediation = 0; sta->hs20_deauth_requested = 0; + sta->hs20_deauth_on_ack = 0; for (;;) { if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_VENDOR_SPECIFIC, @@ -2448,6 +2486,9 @@ int ieee802_1x_init(struct hostapd_data *hapd) conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len; conf.erp_send_reauth_start = hapd->conf->erp_send_reauth_start; conf.erp_domain = hapd->conf->erp_domain; +#ifdef CONFIG_TESTING_OPTIONS + conf.eap_skip_prot_success = hapd->conf->eap_skip_prot_success; +#endif /* CONFIG_TESTING_OPTIONS */ os_memset(&cb, 0, sizeof(cb)); cb.eapol_send = ieee802_1x_eapol_send; |