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:
James Prestwood 2019-05-07 09:50:47 -07:00 committed by Denis Kenzior
parent e282d1fedf
commit d1286200e9
1 changed files with 64 additions and 104 deletions

View File

@ -1548,7 +1548,6 @@ static bool netdev_ft_process_associate(struct netdev *netdev,
const uint8_t *rsne = NULL;
const uint8_t *mde = NULL;
const uint8_t *fte = NULL;
bool transition = netdev->in_ft;
const uint8_t *sent_mde = hs->mde;
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
* advertised by the target AP in Beacon and Probe Response frames."
*/
if (transition && is_rsn) {
if (is_rsn) {
struct ie_rsn_info msg4_rsne;
if (!rsne)
@ -1607,20 +1606,18 @@ static bool netdev_ft_process_associate(struct netdev *netdev,
if (fte) {
struct ie_ft_info ft_info;
uint8_t mic[16];
if (ie_parse_fast_bss_transition_from_data(fte, fte[1] + 2,
&ft_info) < 0)
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
* 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))
return false;
@ -1672,28 +1669,6 @@ static bool netdev_ft_process_associate(struct netdev *netdev,
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);
}
}
return true;
@ -2423,7 +2398,10 @@ static void netdev_associate_event(struct l_genl_msg *msg,
netdev->sm = eapol_sm_new(netdev->handshake);
eapol_register(netdev->sm);
goto auth_complete;
/* Just in case this was a retry */
netdev->ignore_connect_event = false;
return;
} else if (ret == -EAGAIN) {
/*
* Here to support OWE retries. OWE will retry
@ -2437,6 +2415,9 @@ static void netdev_associate_event(struct l_genl_msg *msg,
goto assoc_failed;
}
if (netdev->in_ft) {
bool is_rsn = netdev->handshake->supplicant_ie != NULL;
if (!netdev_ft_process_associate(netdev, frame, frame_len,
&status_code))
goto assoc_failed;
@ -2444,32 +2425,11 @@ static void netdev_associate_event(struct l_genl_msg *msg,
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) {
bool is_rsn = netdev->handshake->supplicant_ie != NULL;
netdev->in_ft = false;
if (is_rsn) {
if (is_rsn)
handshake_state_install_ptk(netdev->handshake);
return;
}
} else if (netdev->sm)
return;
netdev_connect_ok(netdev);
return;