mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-29 13:59:24 +01:00
fils: netdev: update to use auth_proto concepts
This commit is contained in:
parent
f0de2516ea
commit
8317b96e7d
122
src/fils.c
122
src/fils.c
@ -34,18 +34,19 @@
|
|||||||
#include "src/util.h"
|
#include "src/util.h"
|
||||||
#include "src/missing.h"
|
#include "src/missing.h"
|
||||||
#include "src/erp.h"
|
#include "src/erp.h"
|
||||||
|
#include "src/auth-proto.h"
|
||||||
|
|
||||||
#define FILS_NONCE_LEN 16
|
#define FILS_NONCE_LEN 16
|
||||||
#define FILS_SESSION_LEN 8
|
#define FILS_SESSION_LEN 8
|
||||||
|
|
||||||
struct fils_sm {
|
struct fils_sm {
|
||||||
|
struct auth_proto ap;
|
||||||
struct erp_state *erp;
|
struct erp_state *erp;
|
||||||
struct handshake_state *hs;
|
struct handshake_state *hs;
|
||||||
void *user_data;
|
void *user_data;
|
||||||
|
|
||||||
fils_tx_authenticate_func_t auth;
|
fils_tx_authenticate_func_t auth;
|
||||||
fils_tx_associate_func_t assoc;
|
fils_tx_associate_func_t assoc;
|
||||||
fils_complete_func_t complete;
|
|
||||||
|
|
||||||
uint8_t nonce[FILS_NONCE_LEN];
|
uint8_t nonce[FILS_NONCE_LEN];
|
||||||
uint8_t anonce[FILS_NONCE_LEN];
|
uint8_t anonce[FILS_NONCE_LEN];
|
||||||
@ -58,15 +59,8 @@ struct fils_sm {
|
|||||||
uint8_t pmk[48];
|
uint8_t pmk[48];
|
||||||
size_t pmk_len;
|
size_t pmk_len;
|
||||||
uint8_t pmkid[16];
|
uint8_t pmkid[16];
|
||||||
|
|
||||||
bool in_auth : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void fils_failed(struct fils_sm *fils, uint16_t status, bool ap_reject)
|
|
||||||
{
|
|
||||||
fils->complete(status, fils->in_auth, ap_reject, fils->user_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fils_derive_pmkid(struct fils_sm *fils, const uint8_t *erp_data,
|
static void fils_derive_pmkid(struct fils_sm *fils, const uint8_t *erp_data,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
@ -237,34 +231,20 @@ static int fils_derive_key_data(struct fils_sm *fils)
|
|||||||
fils->assoc(iov, 2, fils->kek_and_tk, fils->kek_len, data,
|
fils->assoc(iov, 2, fils->kek_and_tk, fils->kek_len, data,
|
||||||
FILS_NONCE_LEN * 2, fils->user_data);
|
FILS_NONCE_LEN * 2, fils->user_data);
|
||||||
|
|
||||||
fils->in_auth = false;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fils_sm *fils_sm_new(struct handshake_state *hs,
|
static bool fils_start(struct auth_proto *driver)
|
||||||
fils_tx_authenticate_func_t auth,
|
|
||||||
fils_tx_associate_func_t assoc,
|
|
||||||
fils_complete_func_t complete, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct fils_sm *fils;
|
struct fils_sm *fils = l_container_of(driver, struct fils_sm, ap);
|
||||||
|
|
||||||
fils = l_new(struct fils_sm, 1);
|
return erp_start(fils->erp);
|
||||||
|
|
||||||
fils->auth = auth;
|
|
||||||
fils->assoc = assoc;
|
|
||||||
fils->complete = complete;
|
|
||||||
fils->user_data = user_data;
|
|
||||||
fils->hs = hs;
|
|
||||||
fils->in_auth = true;
|
|
||||||
|
|
||||||
fils->erp = erp_new(hs->erp_cache, fils_erp_tx_func, fils);
|
|
||||||
|
|
||||||
return fils;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fils_sm_free(struct fils_sm *fils)
|
static void fils_free(struct auth_proto *driver)
|
||||||
{
|
{
|
||||||
|
struct fils_sm *fils = l_container_of(driver, struct fils_sm, ap);
|
||||||
|
|
||||||
erp_free(fils->erp);
|
erp_free(fils->erp);
|
||||||
|
|
||||||
explicit_bzero(fils->ick, sizeof(fils->ick));
|
explicit_bzero(fils->ick, sizeof(fils->ick));
|
||||||
@ -275,16 +255,10 @@ void fils_sm_free(struct fils_sm *fils)
|
|||||||
l_free(fils);
|
l_free(fils);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fils_start(struct fils_sm *fils)
|
static int fils_rx_authenticate(struct auth_proto *driver, const uint8_t *frame,
|
||||||
{
|
|
||||||
if (!erp_start(fils->erp))
|
|
||||||
fils->complete(MMPDU_STATUS_CODE_UNSPECIFIED, fils->in_auth,
|
|
||||||
false, fils->user_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fils_rx_authenticate(struct fils_sm *fils, const uint8_t *frame,
|
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
|
struct fils_sm *fils = l_container_of(driver, struct fils_sm, ap);
|
||||||
const struct mmpdu_header *hdr = mpdu_validate(frame, len);
|
const struct mmpdu_header *hdr = mpdu_validate(frame, len);
|
||||||
const struct mmpdu_authentication *auth;
|
const struct mmpdu_authentication *auth;
|
||||||
struct ie_tlv_iter iter;
|
struct ie_tlv_iter iter;
|
||||||
@ -295,27 +269,25 @@ void fils_rx_authenticate(struct fils_sm *fils, const uint8_t *frame,
|
|||||||
|
|
||||||
if (!hdr) {
|
if (!hdr) {
|
||||||
l_debug("Auth frame header did not validate");
|
l_debug("Auth frame header did not validate");
|
||||||
goto auth_failed;
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
auth = mmpdu_body(hdr);
|
auth = mmpdu_body(hdr);
|
||||||
|
|
||||||
if (!auth) {
|
if (!auth) {
|
||||||
l_debug("Auth frame body did not validate");
|
l_debug("Auth frame body did not validate");
|
||||||
goto auth_failed;
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auth->status != 0) {
|
if (auth->status != 0) {
|
||||||
l_debug("invalid status %u", auth->status);
|
l_debug("invalid status %u", auth->status);
|
||||||
fils_failed(fils, auth->status, true);
|
return (int)auth->status;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auth->algorithm != MMPDU_AUTH_ALGO_FILS_SK &&
|
if (auth->algorithm != MMPDU_AUTH_ALGO_FILS_SK &&
|
||||||
auth->algorithm != MMPDU_AUTH_ALGO_FILS_SK_PFS) {
|
auth->algorithm != MMPDU_AUTH_ALGO_FILS_SK_PFS) {
|
||||||
l_debug("invalid auth algorithm %u", auth->algorithm);
|
l_debug("invalid auth algorithm %u", auth->algorithm);
|
||||||
fils_failed(fils, MMPDU_STATUS_CODE_UNSUP_AUTH_ALG, false);
|
return MMPDU_STATUS_CODE_UNSUP_AUTH_ALG;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ie_tlv_iter_init(&iter, auth->ies, (const uint8_t *) hdr + len -
|
ie_tlv_iter_init(&iter, auth->ies, (const uint8_t *) hdr + len -
|
||||||
@ -324,13 +296,13 @@ void fils_rx_authenticate(struct fils_sm *fils, const uint8_t *frame,
|
|||||||
switch (iter.tag) {
|
switch (iter.tag) {
|
||||||
case IE_TYPE_FILS_NONCE:
|
case IE_TYPE_FILS_NONCE:
|
||||||
if (iter.len != FILS_NONCE_LEN)
|
if (iter.len != FILS_NONCE_LEN)
|
||||||
goto auth_failed;
|
goto invalid_ies;
|
||||||
|
|
||||||
anonce = iter.data;
|
anonce = iter.data;
|
||||||
break;
|
break;
|
||||||
case IE_TYPE_FILS_SESSION:
|
case IE_TYPE_FILS_SESSION:
|
||||||
if (iter.len != FILS_SESSION_LEN)
|
if (iter.len != FILS_SESSION_LEN)
|
||||||
goto auth_failed;
|
goto invalid_ies;
|
||||||
|
|
||||||
session = iter.data;
|
session = iter.data;
|
||||||
break;
|
break;
|
||||||
@ -345,24 +317,24 @@ void fils_rx_authenticate(struct fils_sm *fils, const uint8_t *frame,
|
|||||||
|
|
||||||
if (!anonce || !session || !wrapped) {
|
if (!anonce || !session || !wrapped) {
|
||||||
l_debug("Auth did not include required IEs");
|
l_debug("Auth did not include required IEs");
|
||||||
fils_failed(fils, MMPDU_STATUS_CODE_INVALID_ELEMENT, false);
|
goto invalid_ies;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(fils->anonce, anonce, FILS_NONCE_LEN);
|
memcpy(fils->anonce, anonce, FILS_NONCE_LEN);
|
||||||
|
|
||||||
if (erp_rx_packet(fils->erp, wrapped, wrapped_len) < 0)
|
if (erp_rx_packet(fils->erp, wrapped, wrapped_len) < 0)
|
||||||
goto auth_failed;
|
goto invalid_ies;
|
||||||
|
|
||||||
fils_derive_key_data(fils);
|
return fils_derive_key_data(fils);
|
||||||
return;
|
|
||||||
|
|
||||||
auth_failed:
|
invalid_ies:
|
||||||
fils_failed(fils, MMPDU_REASON_CODE_UNSPECIFIED, false);
|
return MMPDU_STATUS_CODE_INVALID_ELEMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fils_rx_associate(struct fils_sm *fils, const uint8_t *frame, size_t len)
|
static int fils_rx_associate(struct auth_proto *driver, const uint8_t *frame,
|
||||||
|
size_t len)
|
||||||
{
|
{
|
||||||
|
struct fils_sm *fils = l_container_of(driver, struct fils_sm, ap);
|
||||||
const struct mmpdu_header *hdr = mpdu_validate(frame, len);
|
const struct mmpdu_header *hdr = mpdu_validate(frame, len);
|
||||||
const struct mmpdu_association_response *assoc;
|
const struct mmpdu_association_response *assoc;
|
||||||
struct ie_tlv_iter iter;
|
struct ie_tlv_iter iter;
|
||||||
@ -381,20 +353,18 @@ void fils_rx_associate(struct fils_sm *fils, const uint8_t *frame, size_t len)
|
|||||||
|
|
||||||
if (!hdr) {
|
if (!hdr) {
|
||||||
l_debug("Assoc frame header did not validate");
|
l_debug("Assoc frame header did not validate");
|
||||||
goto assoc_failed;
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
assoc = mmpdu_body(hdr);
|
assoc = mmpdu_body(hdr);
|
||||||
|
|
||||||
if (!assoc) {
|
if (!assoc) {
|
||||||
l_debug("Assoc frame body did not validate");
|
l_debug("Assoc frame body did not validate");
|
||||||
goto assoc_failed;;
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (assoc->status_code != 0) {
|
if (assoc->status_code != 0)
|
||||||
fils_failed(fils, assoc->status_code, true);
|
return (int)assoc->status_code;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ie_tlv_iter_init(&iter, assoc->ies, (const uint8_t *) hdr + len -
|
ie_tlv_iter_init(&iter, assoc->ies, (const uint8_t *) hdr + len -
|
||||||
assoc->ies);
|
assoc->ies);
|
||||||
@ -467,7 +437,7 @@ void fils_rx_associate(struct fils_sm *fils, const uint8_t *frame, size_t len)
|
|||||||
|
|
||||||
if (memcmp(ap_key_auth, expected_key_auth, fils->ick_len)) {
|
if (memcmp(ap_key_auth, expected_key_auth, fils->ick_len)) {
|
||||||
l_error("AP KeyAuth did not verify");
|
l_error("AP KeyAuth did not verify");
|
||||||
goto assoc_failed;
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
handshake_state_set_pmk(fils->hs, fils->pmk, fils->pmk_len);
|
handshake_state_set_pmk(fils->hs, fils->pmk, fils->pmk_len);
|
||||||
@ -484,14 +454,32 @@ void fils_rx_associate(struct fils_sm *fils, const uint8_t *frame, size_t len)
|
|||||||
handshake_state_set_ptk(fils->hs, fils->kek_and_tk, fils->kek_len + 16);
|
handshake_state_set_ptk(fils->hs, fils->kek_and_tk, fils->kek_len + 16);
|
||||||
handshake_state_install_ptk(fils->hs);
|
handshake_state_install_ptk(fils->hs);
|
||||||
|
|
||||||
fils->complete(0, fils->in_auth, false, fils->user_data);
|
return 0;
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
assoc_failed:
|
|
||||||
fils_failed(fils, MMPDU_STATUS_CODE_UNSPECIFIED, false);
|
|
||||||
return;
|
|
||||||
|
|
||||||
invalid_ies:
|
invalid_ies:
|
||||||
fils_failed(fils, MMPDU_STATUS_CODE_INVALID_ELEMENT, false);
|
return MMPDU_STATUS_CODE_INVALID_ELEMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct auth_proto *fils_sm_new(struct handshake_state *hs,
|
||||||
|
fils_tx_authenticate_func_t auth,
|
||||||
|
fils_tx_associate_func_t assoc,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct fils_sm *fils;
|
||||||
|
|
||||||
|
fils = l_new(struct fils_sm, 1);
|
||||||
|
|
||||||
|
fils->auth = auth;
|
||||||
|
fils->assoc = assoc;
|
||||||
|
fils->user_data = user_data;
|
||||||
|
fils->hs = hs;
|
||||||
|
|
||||||
|
fils->ap.start = fils_start;
|
||||||
|
fils->ap.free = fils_free;
|
||||||
|
fils->ap.rx_authenticate = fils_rx_authenticate;
|
||||||
|
fils->ap.rx_associate = fils_rx_associate;
|
||||||
|
|
||||||
|
fils->erp = erp_new(hs->erp_cache, fils_erp_tx_func, fils);
|
||||||
|
|
||||||
|
return &fils->ap;
|
||||||
}
|
}
|
||||||
|
14
src/fils.h
14
src/fils.h
@ -30,18 +30,8 @@ typedef void (*fils_tx_associate_func_t)(struct iovec *iov, size_t iov_len,
|
|||||||
const uint8_t *kek, size_t kek_len,
|
const uint8_t *kek, size_t kek_len,
|
||||||
const uint8_t *nonces, size_t nonces_len,
|
const uint8_t *nonces, size_t nonces_len,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
typedef void (*fils_complete_func_t)(uint16_t status, bool in_auth,
|
|
||||||
bool ap_reject, void *user_data);
|
|
||||||
|
|
||||||
struct fils_sm *fils_sm_new(struct handshake_state *hs,
|
struct auth_proto *fils_sm_new(struct handshake_state *hs,
|
||||||
fils_tx_authenticate_func_t auth,
|
fils_tx_authenticate_func_t auth,
|
||||||
fils_tx_associate_func_t assoc,
|
fils_tx_associate_func_t assoc,
|
||||||
fils_complete_func_t complete, void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
void fils_sm_free(struct fils_sm *fils);
|
|
||||||
|
|
||||||
void fils_start(struct fils_sm *fils);
|
|
||||||
|
|
||||||
void fils_rx_authenticate(struct fils_sm *fils, const uint8_t *frame,
|
|
||||||
size_t len);
|
|
||||||
void fils_rx_associate(struct fils_sm *fils, const uint8_t *frame, size_t len);
|
|
||||||
|
105
src/netdev.c
105
src/netdev.c
@ -60,6 +60,7 @@
|
|||||||
#include "src/nl80211util.h"
|
#include "src/nl80211util.h"
|
||||||
#include "src/owe.h"
|
#include "src/owe.h"
|
||||||
#include "src/fils.h"
|
#include "src/fils.h"
|
||||||
|
#include "src/auth-proto.h"
|
||||||
|
|
||||||
#ifndef ENOTSUPP
|
#ifndef ENOTSUPP
|
||||||
#define ENOTSUPP 524
|
#define ENOTSUPP 524
|
||||||
@ -97,7 +98,7 @@ struct netdev {
|
|||||||
struct eapol_sm *sm;
|
struct eapol_sm *sm;
|
||||||
struct sae_sm *sae_sm;
|
struct sae_sm *sae_sm;
|
||||||
struct owe_sm *owe;
|
struct owe_sm *owe;
|
||||||
struct fils_sm *fils;
|
struct auth_proto *ap;
|
||||||
struct handshake_state *handshake;
|
struct handshake_state *handshake;
|
||||||
uint32_t connect_cmd_id;
|
uint32_t connect_cmd_id;
|
||||||
uint32_t disconnect_cmd_id;
|
uint32_t disconnect_cmd_id;
|
||||||
@ -561,6 +562,11 @@ static void netdev_connect_free(struct netdev *netdev)
|
|||||||
netdev->owe = NULL;
|
netdev->owe = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (netdev->ap) {
|
||||||
|
auth_proto_free(netdev->ap);
|
||||||
|
netdev->ap = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
eapol_preauth_cancel(netdev->index);
|
eapol_preauth_cancel(netdev->index);
|
||||||
|
|
||||||
if (netdev->handshake) {
|
if (netdev->handshake) {
|
||||||
@ -2350,6 +2356,8 @@ static void netdev_authenticate_event(struct l_genl_msg *msg,
|
|||||||
const void *data;
|
const void *data;
|
||||||
const uint8_t *frame = NULL;
|
const uint8_t *frame = NULL;
|
||||||
size_t frame_len = 0;
|
size_t frame_len = 0;
|
||||||
|
int ret;
|
||||||
|
uint16_t status_code = MMPDU_STATUS_CODE_UNSPECIFIED;
|
||||||
|
|
||||||
l_debug("");
|
l_debug("");
|
||||||
|
|
||||||
@ -2368,7 +2376,7 @@ static void netdev_authenticate_event(struct l_genl_msg *msg,
|
|||||||
* the FT Associate command is included in the attached frame and is
|
* the FT Associate command is included in the attached frame and is
|
||||||
* not available in the Authenticate command callback.
|
* not available in the Authenticate command callback.
|
||||||
*/
|
*/
|
||||||
if (!netdev->in_ft && !netdev->sae_sm && !netdev->owe && !netdev->fils)
|
if (!netdev->in_ft && !netdev->sae_sm && !netdev->owe && !netdev->ap)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!l_genl_attr_init(&attr, msg)) {
|
if (!l_genl_attr_init(&attr, msg)) {
|
||||||
@ -2385,7 +2393,8 @@ static void netdev_authenticate_event(struct l_genl_msg *msg,
|
|||||||
if (netdev->sae_sm) {
|
if (netdev->sae_sm) {
|
||||||
sae_timeout(netdev->sae_sm);
|
sae_timeout(netdev->sae_sm);
|
||||||
return;
|
return;
|
||||||
}
|
} else if (auth_proto_auth_timeout(netdev->ap))
|
||||||
|
return;
|
||||||
|
|
||||||
goto auth_error;
|
goto auth_error;
|
||||||
|
|
||||||
@ -2410,16 +2419,22 @@ static void netdev_authenticate_event(struct l_genl_msg *msg,
|
|||||||
frame + 26, frame_len - 26);
|
frame + 26, frame_len - 26);
|
||||||
else if (netdev->owe)
|
else if (netdev->owe)
|
||||||
owe_rx_authenticate(netdev->owe);
|
owe_rx_authenticate(netdev->owe);
|
||||||
else if (netdev->fils)
|
else if (netdev->ap) {
|
||||||
fils_rx_authenticate(netdev->fils, frame, frame_len);
|
ret = auth_proto_rx_authenticate(netdev->ap, frame, frame_len);
|
||||||
else
|
if (ret == 0 || ret == -EAGAIN)
|
||||||
|
return;
|
||||||
|
else if (ret > 0)
|
||||||
|
status_code = (uint16_t)ret;
|
||||||
|
|
||||||
|
goto auth_error;
|
||||||
|
} else
|
||||||
goto auth_error;
|
goto auth_error;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auth_error:
|
auth_error:
|
||||||
netdev_connect_failed(netdev, NETDEV_RESULT_AUTHENTICATION_FAILED,
|
netdev_connect_failed(netdev, NETDEV_RESULT_AUTHENTICATION_FAILED,
|
||||||
MMPDU_STATUS_CODE_UNSPECIFIED);
|
status_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netdev_associate_event(struct l_genl_msg *msg,
|
static void netdev_associate_event(struct l_genl_msg *msg,
|
||||||
@ -2431,6 +2446,7 @@ static void netdev_associate_event(struct l_genl_msg *msg,
|
|||||||
size_t frame_len = 0;
|
size_t frame_len = 0;
|
||||||
const uint8_t *frame = NULL;
|
const uint8_t *frame = NULL;
|
||||||
uint16_t status_code = MMPDU_STATUS_CODE_UNSPECIFIED;
|
uint16_t status_code = MMPDU_STATUS_CODE_UNSPECIFIED;
|
||||||
|
int ret;
|
||||||
|
|
||||||
l_debug("");
|
l_debug("");
|
||||||
|
|
||||||
@ -2438,7 +2454,7 @@ static void netdev_associate_event(struct l_genl_msg *msg,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (!netdev->owe && !netdev->in_ft && !netdev->handshake->mde &&
|
if (!netdev->owe && !netdev->in_ft && !netdev->handshake->mde &&
|
||||||
!netdev->fils)
|
!netdev->ap)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!l_genl_attr_init(&attr, msg)) {
|
if (!l_genl_attr_init(&attr, msg)) {
|
||||||
@ -2450,6 +2466,10 @@ static void netdev_associate_event(struct l_genl_msg *msg,
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case NL80211_ATTR_TIMED_OUT:
|
case NL80211_ATTR_TIMED_OUT:
|
||||||
l_warn("association timed out");
|
l_warn("association timed out");
|
||||||
|
|
||||||
|
if (auth_proto_assoc_timeout(netdev->ap))
|
||||||
|
return;
|
||||||
|
|
||||||
goto assoc_failed;
|
goto assoc_failed;
|
||||||
|
|
||||||
case NL80211_ATTR_FRAME:
|
case NL80211_ATTR_FRAME:
|
||||||
@ -2466,9 +2486,27 @@ static void netdev_associate_event(struct l_genl_msg *msg,
|
|||||||
if (netdev->owe) {
|
if (netdev->owe) {
|
||||||
owe_rx_associate(netdev->owe, frame, frame_len);
|
owe_rx_associate(netdev->owe, frame, frame_len);
|
||||||
return;
|
return;
|
||||||
} else if (netdev->fils) {
|
} else if (netdev->ap) {
|
||||||
fils_rx_associate(netdev->fils, frame, frame_len);
|
ret = auth_proto_rx_associate(netdev->ap, frame, frame_len);
|
||||||
|
if (ret == 0) {
|
||||||
|
auth_proto_free(netdev->ap);
|
||||||
|
netdev->ap = NULL;
|
||||||
|
|
||||||
|
netdev->sm = eapol_sm_new(netdev->handshake);
|
||||||
|
eapol_register(netdev->sm);
|
||||||
|
|
||||||
|
goto auth_complete;
|
||||||
|
} else if (ret == -EAGAIN) {
|
||||||
|
/*
|
||||||
|
* Here to support OWE retries. OWE will retry
|
||||||
|
* internally, but a connect even will still be emitted.
|
||||||
|
*/
|
||||||
|
netdev->ignore_connect_event = true;
|
||||||
return;
|
return;
|
||||||
|
} else if (ret > 0)
|
||||||
|
status_code = (uint16_t)ret;
|
||||||
|
|
||||||
|
goto assoc_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!netdev_ft_process_associate(netdev, frame, frame_len,
|
if (!netdev_ft_process_associate(netdev, frame, frame_len,
|
||||||
@ -2478,6 +2516,7 @@ static void netdev_associate_event(struct l_genl_msg *msg,
|
|||||||
if (status_code != 0)
|
if (status_code != 0)
|
||||||
goto assoc_failed;
|
goto assoc_failed;
|
||||||
|
|
||||||
|
auth_complete:
|
||||||
if (netdev->sm) {
|
if (netdev->sm) {
|
||||||
/*
|
/*
|
||||||
* Start processing EAPoL frames now that the state machine
|
* Start processing EAPoL frames now that the state machine
|
||||||
@ -2786,44 +2825,6 @@ static void netdev_fils_tx_associate(struct iovec *iov, size_t iov_len,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netdev_fils_complete(uint16_t status, bool in_auth, bool ap_reject,
|
|
||||||
void *user_data)
|
|
||||||
{
|
|
||||||
struct netdev *netdev = user_data;
|
|
||||||
|
|
||||||
fils_sm_free(netdev->fils);
|
|
||||||
netdev->fils = NULL;
|
|
||||||
|
|
||||||
if (status == 0) {
|
|
||||||
netdev->ignore_connect_event = true;
|
|
||||||
|
|
||||||
/* Register SM for rekeying */
|
|
||||||
netdev->sm = eapol_sm_new(netdev->handshake);
|
|
||||||
eapol_register(netdev->sm);
|
|
||||||
eapol_set_started(netdev->sm);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* There are a few scenarios here:
|
|
||||||
*
|
|
||||||
* 1. AP rejected authentication, this case we are done.
|
|
||||||
* 2. AP accepted either authentication or association where status was
|
|
||||||
* zero, but we failed for some other reason. In these cases we
|
|
||||||
* should set expect_connect_failure which causes a deauth.
|
|
||||||
* 3. AP rejected association. This will be a non zero status code, so
|
|
||||||
* the kernel should know that we have failed the connection.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!ap_reject)
|
|
||||||
netdev->expect_connect_failure = true;
|
|
||||||
|
|
||||||
netdev->result = (in_auth) ? NETDEV_RESULT_AUTHENTICATION_FAILED :
|
|
||||||
NETDEV_RESULT_ASSOCIATION_FAILED;
|
|
||||||
netdev->last_code = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
|
static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
|
||||||
struct scan_bss *bss,
|
struct scan_bss *bss,
|
||||||
struct handshake_state *hs,
|
struct handshake_state *hs,
|
||||||
@ -2958,8 +2959,8 @@ static int netdev_connect_common(struct netdev *netdev,
|
|||||||
sae_start(netdev->sae_sm);
|
sae_start(netdev->sae_sm);
|
||||||
else if (netdev->owe)
|
else if (netdev->owe)
|
||||||
owe_start(netdev->owe);
|
owe_start(netdev->owe);
|
||||||
else if (netdev->fils)
|
else
|
||||||
fils_start(netdev->fils);
|
auth_proto_start(netdev->ap);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2993,9 +2994,9 @@ int netdev_connect(struct netdev *netdev, struct scan_bss *bss,
|
|||||||
break;
|
break;
|
||||||
case IE_RSN_AKM_SUITE_FILS_SHA256:
|
case IE_RSN_AKM_SUITE_FILS_SHA256:
|
||||||
case IE_RSN_AKM_SUITE_FILS_SHA384:
|
case IE_RSN_AKM_SUITE_FILS_SHA384:
|
||||||
netdev->fils = fils_sm_new(hs, netdev_fils_tx_authenticate,
|
netdev->ap = fils_sm_new(hs, netdev_fils_tx_authenticate,
|
||||||
netdev_fils_tx_associate,
|
netdev_fils_tx_associate,
|
||||||
netdev_fils_complete, netdev);
|
netdev);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cmd_connect = netdev_build_cmd_connect(netdev, bss, hs, NULL);
|
cmd_connect = netdev_build_cmd_connect(netdev, bss, hs, NULL);
|
||||||
|
Loading…
Reference in New Issue
Block a user