summaryrefslogtreecommitdiff
path: root/src/ap/ieee802_1x.c
diff options
context:
space:
mode:
authorAndrej Shadura <andrewsh@debian.org>2018-05-07 19:18:59 +0200
committerAndrej Shadura <andrewsh@debian.org>2018-05-07 19:18:59 +0200
commit1c66e25ec3baa25f8fe09f3f240b620a004e7026 (patch)
tree61b44f30cc85673e26ba789d75a2dfe267bd0ba0 /src/ap/ieee802_1x.c
parent1e2b7568b4f69a9da79de660a1a04ef077479628 (diff)
New upstream version 2.7~git20180504+60a5737
Diffstat (limited to 'src/ap/ieee802_1x.c')
-rw-r--r--src/ap/ieee802_1x.c184
1 files changed, 150 insertions, 34 deletions
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 80ff996..51043ba 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -31,6 +31,8 @@
#include "ap_drv_ops.h"
#include "wps_hostapd.h"
#include "hs20.h"
+/* FIX: Not really a good thing to require ieee802_11.h here.. (FILS) */
+#include "ieee802_11.h"
#include "ieee802_1x.h"
@@ -316,6 +318,7 @@ static void ieee802_1x_learn_identity(struct hostapd_data *hapd,
hdr->code != EAP_CODE_INITIATE))
return;
+ eap_erp_update_identity(sm->eap, eap, len);
identity = eap_get_identity(sm->eap, &identity_len);
if (identity == NULL)
return;
@@ -472,7 +475,7 @@ static int add_common_radius_sta_attr(struct hostapd_data *hapd,
}
}
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
if (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) &&
sta->wpa_sm &&
(wpa_key_mgmt_ft(wpa_auth_sta_key_mgmt(sta->wpa_sm)) ||
@@ -485,7 +488,7 @@ static int add_common_radius_sta_attr(struct hostapd_data *hapd,
wpa_printf(MSG_ERROR, "Could not add Mobility-Domain-Id");
return -1;
}
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_IEEE80211R_AP */
if ((hapd->conf->wpa || hapd->conf->osen) && sta->wpa_sm &&
add_common_radius_sta_attr_rsn(hapd, req_attr, sta, msg) < 0)
@@ -588,9 +591,9 @@ int add_common_radius_attr(struct hostapd_data *hapd,
}
-static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
- struct sta_info *sta,
- const u8 *eap, size_t len)
+void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
+ struct sta_info *sta,
+ const u8 *eap, size_t len)
{
struct radius_msg *msg;
struct eapol_state_machine *sm = sta->eapol_sm;
@@ -709,6 +712,41 @@ static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
goto fail;
}
}
+
+ if (sta->roaming_consortium &&
+ !radius_msg_add_wfa(
+ msg, RADIUS_VENDOR_ATTR_WFA_HS20_ROAMING_CONSORTIUM,
+ wpabuf_head(sta->roaming_consortium),
+ wpabuf_len(sta->roaming_consortium))) {
+ wpa_printf(MSG_ERROR,
+ "Could not add HS 2.0 Roaming Consortium");
+ goto fail;
+ }
+
+ if (hapd->conf->t_c_filename) {
+ be32 timestamp;
+
+ if (!radius_msg_add_wfa(
+ msg,
+ RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILENAME,
+ (const u8 *) hapd->conf->t_c_filename,
+ os_strlen(hapd->conf->t_c_filename))) {
+ wpa_printf(MSG_ERROR,
+ "Could not add HS 2.0 T&C Filename");
+ goto fail;
+ }
+
+ timestamp = host_to_be32(hapd->conf->t_c_timestamp);
+ if (!radius_msg_add_wfa(
+ msg,
+ RADIUS_VENDOR_ATTR_WFA_HS20_TIMESTAMP,
+ (const u8 *) &timestamp,
+ sizeof(timestamp))) {
+ wpa_printf(MSG_ERROR,
+ "Could not add HS 2.0 Timestamp");
+ goto fail;
+ }
+ }
}
#endif /* CONFIG_HS20 */
@@ -845,7 +883,7 @@ static void handle_eap(struct hostapd_data *hapd, struct sta_info *sta,
}
-static struct eapol_state_machine *
+struct eapol_state_machine *
ieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta)
{
int flags = 0;
@@ -970,7 +1008,9 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
}
key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm);
- if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) {
+ if (key_mgmt != -1 &&
+ (wpa_key_mgmt_wpa_psk(key_mgmt) || key_mgmt == WPA_KEY_MGMT_OWE ||
+ key_mgmt == WPA_KEY_MGMT_DPP)) {
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - "
"STA is using PSK");
return;
@@ -1113,7 +1153,9 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
}
key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm);
- if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) {
+ if (key_mgmt != -1 &&
+ (wpa_key_mgmt_wpa_psk(key_mgmt) || key_mgmt == WPA_KEY_MGMT_OWE ||
+ key_mgmt == WPA_KEY_MGMT_DPP)) {
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - using PSK");
/*
* Clear any possible EAPOL authenticator state to support
@@ -1154,7 +1196,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
sta->eapol_sm->eap_if->portEnabled = TRUE;
-#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_IEEE80211R_AP
if (sta->auth_alg == WLAN_AUTH_FT) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG,
@@ -1170,10 +1212,32 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
sta->eapol_sm->portValid = TRUE;
if (sta->eapol_sm->eap)
eap_sm_notify_cached(sta->eapol_sm->eap);
- /* TODO: get vlan_id from R0KH using RRB message */
+ ap_sta_bind_vlan(hapd, sta);
+ return;
+ }
+#endif /* CONFIG_IEEE80211R_AP */
+
+#ifdef CONFIG_FILS
+ if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
+ sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
+ sta->auth_alg == WLAN_AUTH_FILS_PK) {
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
+ HOSTAPD_LEVEL_DEBUG,
+ "PMK from FILS - skip IEEE 802.1X/EAP");
+ /* Setup EAPOL state machines to already authenticated state
+ * because of existing FILS information. */
+ sta->eapol_sm->keyRun = TRUE;
+ sta->eapol_sm->eap_if->eapKeyAvailable = TRUE;
+ sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;
+ sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
+ sta->eapol_sm->authSuccess = TRUE;
+ sta->eapol_sm->authFail = FALSE;
+ sta->eapol_sm->portValid = TRUE;
+ if (sta->eapol_sm->eap)
+ eap_sm_notify_cached(sta->eapol_sm->eap);
return;
}
-#endif /* CONFIG_IEEE80211R */
+#endif /* CONFIG_FILS */
pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
if (pmksa) {
@@ -1395,11 +1459,10 @@ static void ieee802_1x_store_radius_class(struct hostapd_data *hapd,
}
} while (class_len < 1);
- nclass[nclass_count].data = os_malloc(class_len);
+ nclass[nclass_count].data = os_memdup(attr_class, class_len);
if (nclass[nclass_count].data == NULL)
break;
- os_memcpy(nclass[nclass_count].data, attr_class, class_len);
nclass[nclass_count].len = class_len;
nclass_count++;
}
@@ -1559,6 +1622,19 @@ static void ieee802_1x_hs20_session_info(struct hostapd_data *hapd,
ap_sta_session_warning_timeout(hapd, sta, warning_time);
}
+
+static void ieee802_1x_hs20_t_c_filtering(struct hostapd_data *hapd,
+ struct sta_info *sta, u8 *pos,
+ size_t len)
+{
+ if (len < 4)
+ return; /* Malformed information */
+ wpa_printf(MSG_DEBUG,
+ "HS 2.0: Terms and Conditions filtering %02x %02x %02x %02x",
+ pos[0], pos[1], pos[2], pos[3]);
+ hs20_t_c_filtering(hapd, sta, pos[0] & BIT(0));
+}
+
#endif /* CONFIG_HS20 */
@@ -1606,6 +1682,9 @@ static void ieee802_1x_check_hs20(struct hostapd_data *hapd,
ieee802_1x_hs20_session_info(hapd, sta, pos, sublen,
session_timeout);
break;
+ case RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING:
+ ieee802_1x_hs20_t_c_filtering(hapd, sta, pos, sublen);
+ break;
}
}
#endif /* CONFIG_HS20 */
@@ -1663,6 +1742,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
struct sta_info *sta;
u32 session_timeout = 0, termination_action, acct_interim_interval;
int session_timeout_set;
+ u32 reason_code;
struct eapol_state_machine *sm;
int override_eapReq = 0;
struct radius_hdr *hdr = radius_msg_get_hdr(msg);
@@ -1788,14 +1868,17 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
break;
sta->session_timeout_set = !!session_timeout_set;
- sta->session_timeout = session_timeout;
+ os_get_reltime(&sta->session_timeout);
+ sta->session_timeout.sec += session_timeout;
/* RFC 3580, Ch. 3.17 */
if (session_timeout_set && termination_action ==
- RADIUS_TERMINATION_ACTION_RADIUS_REQUEST) {
+ RADIUS_TERMINATION_ACTION_RADIUS_REQUEST)
sm->reAuthPeriod = session_timeout;
- } else if (session_timeout_set)
+ else if (session_timeout_set)
ap_sta_session_timeout(hapd, sta, session_timeout);
+ else
+ ap_sta_no_session_timeout(hapd, sta);
sm->eap_if->aaaSuccess = TRUE;
override_eapReq = 1;
@@ -1811,6 +1894,13 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
case RADIUS_CODE_ACCESS_REJECT:
sm->eap_if->aaaFail = TRUE;
override_eapReq = 1;
+ if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_WLAN_REASON_CODE,
+ &reason_code) == 0) {
+ wpa_printf(MSG_DEBUG,
+ "RADIUS server indicated WLAN-Reason-Code %u in Access-Reject for "
+ MACSTR, reason_code, MAC2STR(sta->addr));
+ sta->disconnect_reason_code = reason_code;
+ }
break;
case RADIUS_CODE_ACCESS_CHALLENGE:
sm->eap_if->aaaEapReq = TRUE;
@@ -1837,6 +1927,19 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
if (override_eapReq)
sm->eap_if->aaaEapReq = FALSE;
+#ifdef CONFIG_FILS
+#ifdef NEED_AP_MLME
+ if (sta->flags & WLAN_STA_PENDING_FILS_ERP) {
+ /* TODO: Add a PMKSA entry on success? */
+ ieee802_11_finish_fils_auth(
+ hapd, sta, hdr->code == RADIUS_CODE_ACCESS_ACCEPT,
+ sm->eap_if->aaaEapReqData,
+ sm->eap_if->aaaEapKeyData,
+ sm->eap_if->aaaEapKeyDataLen);
+ }
+#endif /* NEED_AP_MLME */
+#endif /* CONFIG_FILS */
+
eapol_auth_step(sm);
return RADIUS_RX_QUEUED;
@@ -1924,7 +2027,7 @@ static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
wpa_printf(MSG_DEBUG, "IEEE 802.1X: New default WEP key index %d",
eapol->default_wep_key_idx);
-
+
if (ieee802_1x_rekey_broadcast(hapd)) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_WARNING, "failed to generate a "
@@ -2034,11 +2137,10 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity,
}
if (eap_user->password) {
- user->password = os_malloc(eap_user->password_len);
+ user->password = os_memdup(eap_user->password,
+ eap_user->password_len);
if (user->password == NULL)
goto out;
- os_memcpy(user->password, eap_user->password,
- eap_user->password_len);
user->password_len = eap_user->password_len;
user->password_hash = eap_user->password_hash;
}
@@ -2190,6 +2292,7 @@ int ieee802_1x_init(struct hostapd_data *hapd)
conf.erp_domain = hapd->conf->erp_domain;
conf.erp = hapd->conf->eap_server_erp;
conf.tls_session_lifetime = hapd->conf->tls_session_lifetime;
+ conf.tls_flags = hapd->conf->tls_flags;
conf.pac_opaque_encr_key = hapd->conf->pac_opaque_encr_key;
conf.eap_fast_a_id = hapd->conf->eap_fast_a_id;
conf.eap_fast_a_id_len = hapd->conf->eap_fast_a_id_len;
@@ -2326,6 +2429,16 @@ int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
MAC2STR(sta->addr), xhdr->version, xhdr->type,
be_to_host16(xhdr->length), ack);
+#ifdef CONFIG_WPS
+ if (xhdr->type == IEEE802_1X_TYPE_EAP_PACKET && ack &&
+ (sta->flags & WLAN_STA_WPS) &&
+ ap_sta_pending_delayed_1x_auth_fail_disconnect(hapd, sta)) {
+ wpa_printf(MSG_DEBUG,
+ "WPS: Indicate EAP completion on ACK for EAP-Failure");
+ hostapd_wps_eap_completed(hapd);
+ }
+#endif /* CONFIG_WPS */
+
if (xhdr->type != IEEE802_1X_TYPE_EAPOL_KEY)
return 0;
@@ -2642,6 +2755,13 @@ static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx)
hs20_send_wnm_notification_deauth_req(hapd, sta->addr,
sta->hs20_deauth_req);
}
+
+ if (sta->hs20_t_c_filtering) {
+ wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to "
+ MACSTR " to indicate Terms and Conditions filtering",
+ MAC2STR(sta->addr));
+ hs20_send_wnm_notification_t_c(hapd, sta->addr);
+ }
}
#endif /* CONFIG_HS20 */
@@ -2655,6 +2775,7 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
/* TODO: get PMKLifetime from WPA parameters */
static const int dot11RSNAConfigPMKLifetime = 43200;
unsigned int session_timeout;
+ struct os_reltime now, remaining;
#ifdef CONFIG_HS20
if (remediation && !sta->remediation) {
@@ -2665,7 +2786,8 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
sta->remediation_method = 1; /* SOAP-XML SPP */
}
- if (success && (sta->remediation || sta->hs20_deauth_req)) {
+ if (success && (sta->remediation || sta->hs20_deauth_req ||
+ sta->hs20_t_c_filtering)) {
wpa_printf(MSG_DEBUG, "HS 2.0: Schedule WNM-Notification to "
MACSTR " in 100 ms", MAC2STR(sta->addr));
eloop_cancel_timeout(ieee802_1x_wnm_notif_send, hapd, sta);
@@ -2675,10 +2797,13 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
#endif /* CONFIG_HS20 */
key = ieee802_1x_get_key(sta->eapol_sm, &len);
- if (sta->session_timeout_set)
- session_timeout = sta->session_timeout;
- else
+ if (sta->session_timeout_set) {
+ os_get_reltime(&now);
+ os_reltime_sub(&sta->session_timeout, &now, &remaining);
+ session_timeout = (remaining.sec > 0) ? remaining.sec : 1;
+ } else {
session_timeout = dot11RSNAConfigPMKLifetime;
+ }
if (success && key && len >= PMK_LEN && !sta->remediation &&
!sta->hs20_deauth_requested &&
wpa_auth_pmksa_add(sta->wpa_sm, key, len, session_timeout,
@@ -2699,15 +2824,6 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
* EAP-FAST with anonymous provisioning, may require another
* EAPOL authentication to be started to complete connection.
*/
- wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "IEEE 802.1X: Force "
- "disconnection after EAP-Failure");
- /* Add a small sleep to increase likelihood of previously
- * requested EAP-Failure TX getting out before this should the
- * driver reorder operations.
- */
- os_sleep(0, 10000);
- ap_sta_disconnect(hapd, sta, sta->addr,
- WLAN_REASON_IEEE_802_1X_AUTH_FAILED);
- hostapd_wps_eap_completed(hapd);
+ ap_sta_delayed_1x_auth_fail_disconnect(hapd, sta);
}
}