aboutsummaryrefslogtreecommitdiff
path: root/src/ap/ieee802_1x.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ap/ieee802_1x.c')
-rw-r--r--src/ap/ieee802_1x.c63
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;