mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-22 23:09:34 +01:00
netdev: move connect completion into netdev_connect_event
The duplicate/similar code in netdev_associate_event and netdev_connect_event leads to very hard to follow code, especially when you throw OWE/SAE/FILS or full mac cards into the mix. Currently these protocols finish the connection inside netdev_associate_event, and set ignore_connect_event. But for full mac cards we must finish the connection in netdev_connect_event. In attempt to simplify this, all connections will be completed and/or the 4-way started in netdev_connect_event. This satisfies both soft/full mac cards as well as simplifies the FT processing in netdev_associate_event. Since the FT IEs can be processed in netdev_connect_event (as they already are to support full mac) we can assume that any FT processing inside netdev_associate_event is for a fast transition, not initial mobility association. This simplifies netdev_ft_process_associate by removing all the blocks that would get hit if transition == false. Handling FT this way also fixes FT-SAE which was broken after the auth-proto changes since the initial mobility association was never processed if there was an auth-proto running.
This commit is contained in:
parent
e282d1fedf
commit
d1286200e9
168
src/netdev.c
168
src/netdev.c
@ -1548,7 +1548,6 @@ static bool netdev_ft_process_associate(struct netdev *netdev,
|
|||||||
const uint8_t *rsne = NULL;
|
const uint8_t *rsne = NULL;
|
||||||
const uint8_t *mde = NULL;
|
const uint8_t *mde = NULL;
|
||||||
const uint8_t *fte = NULL;
|
const uint8_t *fte = NULL;
|
||||||
bool transition = netdev->in_ft;
|
|
||||||
const uint8_t *sent_mde = hs->mde;
|
const uint8_t *sent_mde = hs->mde;
|
||||||
bool is_rsn = hs->supplicant_ie != NULL;
|
bool is_rsn = hs->supplicant_ie != NULL;
|
||||||
|
|
||||||
@ -1569,7 +1568,7 @@ static bool netdev_ft_process_associate(struct netdev *netdev,
|
|||||||
* — All other fields shall be identical to the contents of the RSNE
|
* — All other fields shall be identical to the contents of the RSNE
|
||||||
* advertised by the target AP in Beacon and Probe Response frames."
|
* advertised by the target AP in Beacon and Probe Response frames."
|
||||||
*/
|
*/
|
||||||
if (transition && is_rsn) {
|
if (is_rsn) {
|
||||||
struct ie_rsn_info msg4_rsne;
|
struct ie_rsn_info msg4_rsne;
|
||||||
|
|
||||||
if (!rsne)
|
if (!rsne)
|
||||||
@ -1607,92 +1606,68 @@ static bool netdev_ft_process_associate(struct netdev *netdev,
|
|||||||
|
|
||||||
if (fte) {
|
if (fte) {
|
||||||
struct ie_ft_info ft_info;
|
struct ie_ft_info ft_info;
|
||||||
|
uint8_t mic[16];
|
||||||
|
|
||||||
if (ie_parse_fast_bss_transition_from_data(fte, fte[1] + 2,
|
if (ie_parse_fast_bss_transition_from_data(fte, fte[1] + 2,
|
||||||
&ft_info) < 0)
|
&ft_info) < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Validate the FTE contents */
|
/*
|
||||||
if (transition) {
|
* In an RSN, check for an FT IE with the same
|
||||||
/*
|
* R0KH-ID, R1KH-ID, ANonce and SNonce that we
|
||||||
* In an RSN, check for an FT IE with the same
|
* received in message 2, MIC Element Count
|
||||||
* R0KH-ID, R1KH-ID, ANonce and SNonce that we
|
* of 6 and the correct MIC.
|
||||||
* received in message 2, MIC Element Count
|
*/
|
||||||
* of 6 and the correct MIC.
|
|
||||||
*/
|
|
||||||
uint8_t mic[16];
|
|
||||||
|
|
||||||
if (!ft_calculate_fte_mic(hs, 6, rsne, fte, NULL, mic))
|
if (!ft_calculate_fte_mic(hs, 6, rsne, fte, NULL, mic))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ft_info.mic_element_count != 3 ||
|
||||||
|
memcmp(ft_info.mic, mic, 16))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (hs->r0khid_len != ft_info.r0khid_len ||
|
||||||
|
memcmp(hs->r0khid, ft_info.r0khid,
|
||||||
|
hs->r0khid_len) ||
|
||||||
|
!ft_info.r1khid_present ||
|
||||||
|
memcmp(hs->r1khid, ft_info.r1khid, 6))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (memcmp(ft_info.anonce, hs->anonce, 32))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (memcmp(ft_info.snonce, hs->snonce, 32))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ft_info.gtk_len) {
|
||||||
|
uint8_t gtk[32];
|
||||||
|
|
||||||
|
if (!handshake_decode_fte_key(hs, ft_info.gtk,
|
||||||
|
ft_info.gtk_len,
|
||||||
|
gtk))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (ft_info.mic_element_count != 3 ||
|
if (ft_info.gtk_rsc[6] != 0x00 ||
|
||||||
memcmp(ft_info.mic, mic, 16))
|
ft_info.gtk_rsc[7] != 0x00)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (hs->r0khid_len != ft_info.r0khid_len ||
|
handshake_state_install_gtk(hs,
|
||||||
memcmp(hs->r0khid, ft_info.r0khid,
|
ft_info.gtk_key_id,
|
||||||
hs->r0khid_len) ||
|
gtk, ft_info.gtk_len,
|
||||||
!ft_info.r1khid_present ||
|
ft_info.gtk_rsc, 6);
|
||||||
memcmp(hs->r1khid, ft_info.r1khid, 6))
|
}
|
||||||
|
|
||||||
|
if (ft_info.igtk_len) {
|
||||||
|
uint8_t igtk[16];
|
||||||
|
|
||||||
|
if (!handshake_decode_fte_key(hs, ft_info.igtk,
|
||||||
|
ft_info.igtk_len, igtk))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (memcmp(ft_info.anonce, hs->anonce, 32))
|
handshake_state_install_igtk(hs,
|
||||||
return false;
|
ft_info.igtk_key_id,
|
||||||
|
igtk, ft_info.igtk_len,
|
||||||
if (memcmp(ft_info.snonce, hs->snonce, 32))
|
ft_info.igtk_ipn);
|
||||||
return false;
|
|
||||||
|
|
||||||
if (ft_info.gtk_len) {
|
|
||||||
uint8_t gtk[32];
|
|
||||||
|
|
||||||
if (!handshake_decode_fte_key(hs, ft_info.gtk,
|
|
||||||
ft_info.gtk_len,
|
|
||||||
gtk))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (ft_info.gtk_rsc[6] != 0x00 ||
|
|
||||||
ft_info.gtk_rsc[7] != 0x00)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
handshake_state_install_gtk(hs,
|
|
||||||
ft_info.gtk_key_id,
|
|
||||||
gtk, ft_info.gtk_len,
|
|
||||||
ft_info.gtk_rsc, 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ft_info.igtk_len) {
|
|
||||||
uint8_t igtk[16];
|
|
||||||
|
|
||||||
if (!handshake_decode_fte_key(hs, ft_info.igtk,
|
|
||||||
ft_info.igtk_len, igtk))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
handshake_state_install_igtk(hs,
|
|
||||||
ft_info.igtk_key_id,
|
|
||||||
igtk, ft_info.igtk_len,
|
|
||||||
ft_info.igtk_ipn);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Initial MD association */
|
|
||||||
|
|
||||||
uint8_t zeros[32] = {};
|
|
||||||
|
|
||||||
handshake_state_set_fte(hs, fte);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 12.4.2: "The FTE shall have a MIC information
|
|
||||||
* element count of zero (i.e., no MIC present)
|
|
||||||
* and have ANonce, SNonce, and MIC fields set to 0."
|
|
||||||
*/
|
|
||||||
if (ft_info.mic_element_count != 0 ||
|
|
||||||
memcmp(ft_info.mic, zeros, 16) ||
|
|
||||||
memcmp(ft_info.anonce, zeros, 32) ||
|
|
||||||
memcmp(ft_info.snonce, zeros, 32))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
handshake_state_set_kh_ids(hs, ft_info.r0khid,
|
|
||||||
ft_info.r0khid_len,
|
|
||||||
ft_info.r1khid);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2423,7 +2398,10 @@ static void netdev_associate_event(struct l_genl_msg *msg,
|
|||||||
netdev->sm = eapol_sm_new(netdev->handshake);
|
netdev->sm = eapol_sm_new(netdev->handshake);
|
||||||
eapol_register(netdev->sm);
|
eapol_register(netdev->sm);
|
||||||
|
|
||||||
goto auth_complete;
|
/* Just in case this was a retry */
|
||||||
|
netdev->ignore_connect_event = false;
|
||||||
|
|
||||||
|
return;
|
||||||
} else if (ret == -EAGAIN) {
|
} else if (ret == -EAGAIN) {
|
||||||
/*
|
/*
|
||||||
* Here to support OWE retries. OWE will retry
|
* Here to support OWE retries. OWE will retry
|
||||||
@ -2437,39 +2415,21 @@ static void netdev_associate_event(struct l_genl_msg *msg,
|
|||||||
goto assoc_failed;
|
goto assoc_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!netdev_ft_process_associate(netdev, frame, frame_len,
|
|
||||||
&status_code))
|
|
||||||
goto assoc_failed;
|
|
||||||
|
|
||||||
if (status_code != 0)
|
|
||||||
goto assoc_failed;
|
|
||||||
|
|
||||||
auth_complete:
|
|
||||||
if (netdev->sm) {
|
|
||||||
/*
|
|
||||||
* Start processing EAPoL frames now that the state machine
|
|
||||||
* has all the input data even in FT mode.
|
|
||||||
*/
|
|
||||||
if (!eapol_start(netdev->sm))
|
|
||||||
goto assoc_failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Connection can be fully handled here, not in connect event */
|
|
||||||
netdev->ignore_connect_event = true;
|
|
||||||
|
|
||||||
if (netdev->in_ft) {
|
if (netdev->in_ft) {
|
||||||
bool is_rsn = netdev->handshake->supplicant_ie != NULL;
|
bool is_rsn = netdev->handshake->supplicant_ie != NULL;
|
||||||
|
|
||||||
|
if (!netdev_ft_process_associate(netdev, frame, frame_len,
|
||||||
|
&status_code))
|
||||||
|
goto assoc_failed;
|
||||||
|
|
||||||
|
if (status_code != 0)
|
||||||
|
goto assoc_failed;
|
||||||
|
|
||||||
netdev->in_ft = false;
|
netdev->in_ft = false;
|
||||||
|
|
||||||
if (is_rsn) {
|
if (is_rsn)
|
||||||
handshake_state_install_ptk(netdev->handshake);
|
handshake_state_install_ptk(netdev->handshake);
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
} else if (netdev->sm)
|
|
||||||
return;
|
|
||||||
|
|
||||||
netdev_connect_ok(netdev);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user