mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-20 19:12:33 +01:00
eapol: Only send EAPOL-Start on step 1/4 if really needed
Currently we'd send EAPOL-Start whenever EAP was configured and we received an EAPOL-Key before EAP negotiation. Instead only do that if we know we can't respond to the 4-Way handshake because we don't have a PMK yet or the PMKID doesn't match. Require a PMKID in step 1/4 if we'd sent a list of PMKIDs in our RSNE.
This commit is contained in:
parent
f53cb22b7e
commit
48966f57e8
66
src/eapol.c
66
src/eapol.c
@ -843,10 +843,57 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm,
|
|||||||
uint8_t *ies;
|
uint8_t *ies;
|
||||||
size_t ies_len;
|
size_t ies_len;
|
||||||
const uint8_t *own_ie = sm->handshake->own_ie;
|
const uint8_t *own_ie = sm->handshake->own_ie;
|
||||||
|
const uint8_t *pmkid;
|
||||||
|
struct ie_rsn_info rsn_info;
|
||||||
|
|
||||||
if (!eapol_verify_ptk_1_of_4(ek))
|
if (!eapol_verify_ptk_1_of_4(ek))
|
||||||
goto error_unspecified;
|
goto error_unspecified;
|
||||||
|
|
||||||
|
pmkid = handshake_util_find_pmkid_kde(ek->key_data,
|
||||||
|
L_BE16_TO_CPU(ek->key_data_len));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Require the PMKID KDE whenever we've sent a list of PMKIDs in
|
||||||
|
* our RSNE, otherwise treat it as optional and only validate it
|
||||||
|
* against our PMK. Some 802.11-2012 sections show message 1/4
|
||||||
|
* without a PMKID KDE and there are APs that send no PMKID KDE.
|
||||||
|
*/
|
||||||
|
if (!sm->handshake->wpa_ie &&
|
||||||
|
ie_parse_rsne_from_data(own_ie, own_ie[1] + 2,
|
||||||
|
&rsn_info) >= 0 &&
|
||||||
|
rsn_info.num_pmkids) {
|
||||||
|
bool found = false;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!pmkid)
|
||||||
|
goto error_unspecified;
|
||||||
|
|
||||||
|
for (i = 0; i < rsn_info.num_pmkids; i++)
|
||||||
|
if (!memcmp(rsn_info.pmkids + i * 16, pmkid, 16)) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
goto error_unspecified;
|
||||||
|
} else if (pmkid) {
|
||||||
|
uint8_t own_pmkid[16];
|
||||||
|
|
||||||
|
if (handshake_state_get_pmkid(sm->handshake, own_pmkid) &&
|
||||||
|
memcmp(pmkid, own_pmkid, 16)) {
|
||||||
|
/*
|
||||||
|
* If the AP has a different PMKSA from ours and we
|
||||||
|
* have means to create a new PMKSA through EAP then
|
||||||
|
* try that, otherwise give up.
|
||||||
|
*/
|
||||||
|
if (sm->eap) {
|
||||||
|
send_eapol_start(NULL, sm);
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
goto error_unspecified;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handshake_state_new_snonce(sm->handshake);
|
handshake_state_new_snonce(sm->handshake);
|
||||||
|
|
||||||
handshake_state_set_anonce(sm->handshake, ek->key_nonce);
|
handshake_state_set_anonce(sm->handshake, ek->key_nonce);
|
||||||
@ -858,7 +905,6 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm,
|
|||||||
(IE_RSN_AKM_SUITE_FT_OVER_8021X |
|
(IE_RSN_AKM_SUITE_FT_OVER_8021X |
|
||||||
IE_RSN_AKM_SUITE_FT_USING_PSK |
|
IE_RSN_AKM_SUITE_FT_USING_PSK |
|
||||||
IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256)) {
|
IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256)) {
|
||||||
struct ie_rsn_info rsn_info;
|
|
||||||
const uint8_t *mde = sm->handshake->mde;
|
const uint8_t *mde = sm->handshake->mde;
|
||||||
const uint8_t *fte = sm->handshake->fte;
|
const uint8_t *fte = sm->handshake->fte;
|
||||||
|
|
||||||
@ -868,10 +914,6 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm,
|
|||||||
*/
|
*/
|
||||||
ies = alloca(512);
|
ies = alloca(512);
|
||||||
|
|
||||||
if (ie_parse_rsne_from_data(own_ie, own_ie[1] + 2,
|
|
||||||
&rsn_info) < 0)
|
|
||||||
goto error_unspecified;
|
|
||||||
|
|
||||||
rsn_info.num_pmkids = 1;
|
rsn_info.num_pmkids = 1;
|
||||||
rsn_info.pmkids = sm->handshake->pmk_r1_name;
|
rsn_info.pmkids = sm->handshake->pmk_r1_name;
|
||||||
|
|
||||||
@ -1533,6 +1575,12 @@ static void eapol_rx_packet(struct eapol_sm *sm,
|
|||||||
if (!sm->protocol_version)
|
if (!sm->protocol_version)
|
||||||
sm->protocol_version = eh->protocol_version;
|
sm->protocol_version = eh->protocol_version;
|
||||||
|
|
||||||
|
/* Only EAPOL-EAP packets allowed in preauthentication */
|
||||||
|
if (sm->preauth && eh->packet_type != 0) {
|
||||||
|
handshake_failed(sm, MPDU_REASON_CODE_UNSPECIFIED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (eh->packet_type) {
|
switch (eh->packet_type) {
|
||||||
case 0: /* EAPOL-EAP */
|
case 0: /* EAPOL-EAP */
|
||||||
l_timeout_remove(sm->eapol_start_timeout);
|
l_timeout_remove(sm->eapol_start_timeout);
|
||||||
@ -1556,7 +1604,10 @@ static void eapol_rx_packet(struct eapol_sm *sm,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: /* EAPOL-Key */
|
case 3: /* EAPOL-Key */
|
||||||
if (sm->eap) {
|
if (!sm->handshake->have_pmk) {
|
||||||
|
if (!sm->eap)
|
||||||
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Either this is an error (EAP negotiation in
|
* Either this is an error (EAP negotiation in
|
||||||
* progress) or the server is giving us a chance to
|
* progress) or the server is giving us a chance to
|
||||||
@ -1569,9 +1620,6 @@ static void eapol_rx_packet(struct eapol_sm *sm,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sm->handshake->have_pmk)
|
|
||||||
return;
|
|
||||||
|
|
||||||
eapol_key_handle(sm, frame, len);
|
eapol_key_handle(sm, frame, len);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user