mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-22 13:02:44 +01:00
netdev: remove FT auth proto
This removes the FT auth-proto from netdev and all associated helpers and APIs.
This commit is contained in:
parent
ad59fb6249
commit
5e731527e5
341
src/netdev.c
341
src/netdev.c
@ -96,13 +96,6 @@ struct netdev_handshake_state {
|
||||
enum connection_type type;
|
||||
};
|
||||
|
||||
struct netdev_ft_over_ds_info {
|
||||
struct ft_ds_info super;
|
||||
struct netdev *netdev;
|
||||
|
||||
bool parsed : 1;
|
||||
};
|
||||
|
||||
struct netdev_ext_key_info {
|
||||
uint16_t proto;
|
||||
bool noencrypt;
|
||||
@ -145,7 +138,6 @@ struct netdev {
|
||||
struct l_timeout *sa_query_delay;
|
||||
struct l_timeout *group_handshake_timeout;
|
||||
uint16_t sa_query_id;
|
||||
uint8_t prev_snonce[32];
|
||||
int8_t rssi_levels[16];
|
||||
uint8_t rssi_levels_num;
|
||||
uint8_t cur_rssi_level_idx;
|
||||
@ -176,8 +168,6 @@ struct netdev {
|
||||
struct l_genl_msg *auth_cmd;
|
||||
struct wiphy_radio_work_item work;
|
||||
|
||||
struct l_queue *ft_ds_list;
|
||||
|
||||
struct netdev_ext_key_info *ext_key_info;
|
||||
|
||||
bool connected : 1;
|
||||
@ -752,13 +742,6 @@ static void netdev_preauth_destroy(void *data)
|
||||
l_free(state);
|
||||
}
|
||||
|
||||
static void netdev_ft_ds_entry_free(void *data)
|
||||
{
|
||||
struct netdev_ft_over_ds_info *info = data;
|
||||
|
||||
ft_ds_info_free(&info->super);
|
||||
}
|
||||
|
||||
static void netdev_connect_free(struct netdev *netdev)
|
||||
{
|
||||
if (netdev->work.id)
|
||||
@ -847,11 +830,6 @@ static void netdev_connect_free(struct netdev *netdev)
|
||||
l_genl_family_cancel(nl80211, netdev->get_oci_cmd_id);
|
||||
netdev->get_oci_cmd_id = 0;
|
||||
}
|
||||
|
||||
if (netdev->ft_ds_list) {
|
||||
l_queue_destroy(netdev->ft_ds_list, netdev_ft_ds_entry_free);
|
||||
netdev->ft_ds_list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void netdev_connect_failed(struct netdev *netdev,
|
||||
@ -962,11 +940,6 @@ static void netdev_free(void *data)
|
||||
if (netdev->fw_roam_bss)
|
||||
scan_bss_free(netdev->fw_roam_bss);
|
||||
|
||||
if (netdev->ft_ds_list) {
|
||||
l_queue_destroy(netdev->ft_ds_list, netdev_ft_ds_entry_free);
|
||||
netdev->ft_ds_list = NULL;
|
||||
}
|
||||
|
||||
scan_wdev_remove(netdev->wdev_id);
|
||||
|
||||
watchlist_destroy(&netdev->station_watches);
|
||||
@ -1424,11 +1397,6 @@ static void netdev_connect_ok(struct netdev *netdev)
|
||||
netdev->connect_cb = NULL;
|
||||
}
|
||||
|
||||
if (netdev->ft_ds_list) {
|
||||
l_queue_destroy(netdev->ft_ds_list, netdev_ft_ds_entry_free);
|
||||
netdev->ft_ds_list = NULL;
|
||||
}
|
||||
|
||||
netdev_rssi_polling_update(netdev);
|
||||
|
||||
if (netdev->work.id)
|
||||
@ -4414,48 +4382,6 @@ static int netdev_tx_ft_frame(uint32_t ifindex, uint16_t frame_type,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void netdev_cmd_authenticate_ft_cb(struct l_genl_msg *msg,
|
||||
void *user_data)
|
||||
{
|
||||
struct netdev *netdev = user_data;
|
||||
|
||||
netdev->connect_cmd_id = 0;
|
||||
|
||||
if (l_genl_msg_get_error(msg) < 0)
|
||||
netdev_connect_failed(netdev,
|
||||
NETDEV_RESULT_AUTHENTICATION_FAILED,
|
||||
MMPDU_STATUS_CODE_UNSPECIFIED);
|
||||
}
|
||||
|
||||
static void netdev_ft_tx_authenticate(struct iovec *iov,
|
||||
size_t iov_len, void *user_data)
|
||||
{
|
||||
struct netdev *netdev = user_data;
|
||||
struct l_genl_msg *cmd_authenticate;
|
||||
|
||||
cmd_authenticate = netdev_build_cmd_authenticate(netdev,
|
||||
NL80211_AUTHTYPE_FT);
|
||||
l_genl_msg_append_attrv(cmd_authenticate, NL80211_ATTR_IE, iov,
|
||||
iov_len);
|
||||
|
||||
netdev->connect_cmd_id = l_genl_family_send(nl80211,
|
||||
cmd_authenticate,
|
||||
netdev_cmd_authenticate_ft_cb,
|
||||
netdev, NULL);
|
||||
if (!netdev->connect_cmd_id) {
|
||||
l_genl_msg_unref(cmd_authenticate);
|
||||
goto restore_snonce;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
restore_snonce:
|
||||
memcpy(netdev->handshake->snonce, netdev->prev_snonce, 32);
|
||||
|
||||
netdev_connect_failed(netdev, NETDEV_RESULT_AUTHENTICATION_FAILED,
|
||||
MMPDU_STATUS_CODE_UNSPECIFIED);
|
||||
}
|
||||
|
||||
static int netdev_ft_tx_associate(uint32_t ifindex, uint32_t freq,
|
||||
const uint8_t *prev_bssid,
|
||||
struct iovec *ft_iov, size_t n_ft_iov)
|
||||
@ -4545,98 +4471,6 @@ static int netdev_ft_tx_associate(uint32_t ifindex, uint32_t freq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void prepare_ft(struct netdev *netdev, const struct scan_bss *target_bss)
|
||||
{
|
||||
struct netdev_handshake_state *nhs;
|
||||
|
||||
/*
|
||||
* We reuse the handshake_state object and reset what's needed.
|
||||
* Could also create a new object and copy most of the state but
|
||||
* we would end up doing more work.
|
||||
*/
|
||||
memcpy(netdev->prev_snonce, netdev->handshake->snonce, 32);
|
||||
|
||||
netdev->frequency = target_bss->frequency;
|
||||
|
||||
handshake_state_set_authenticator_address(netdev->handshake,
|
||||
target_bss->addr);
|
||||
|
||||
if (target_bss->rsne)
|
||||
handshake_state_set_authenticator_ie(netdev->handshake,
|
||||
target_bss->rsne);
|
||||
memcpy(netdev->handshake->mde + 2, target_bss->mde, 3);
|
||||
|
||||
netdev->handshake->active_tk_index = 0;
|
||||
netdev->associated = false;
|
||||
netdev->operational = false;
|
||||
netdev->in_ft = true;
|
||||
|
||||
handshake_state_set_chandef(netdev->handshake, NULL);
|
||||
|
||||
/*
|
||||
* Cancel commands that could be running because of EAPoL activity
|
||||
* like re-keying, this way the callbacks for those commands don't
|
||||
* have to check if failures resulted from the transition.
|
||||
*/
|
||||
nhs = l_container_of(netdev->handshake,
|
||||
struct netdev_handshake_state, super);
|
||||
|
||||
/* reset key states just as we do in initialization */
|
||||
nhs->complete = false;
|
||||
nhs->ptk_installed = false;
|
||||
nhs->gtk_installed = true;
|
||||
nhs->igtk_installed = true;
|
||||
|
||||
if (nhs->group_new_key_cmd_id) {
|
||||
l_genl_family_cancel(nl80211, nhs->group_new_key_cmd_id);
|
||||
nhs->group_new_key_cmd_id = 0;
|
||||
}
|
||||
|
||||
if (nhs->group_management_new_key_cmd_id) {
|
||||
l_genl_family_cancel(nl80211,
|
||||
nhs->group_management_new_key_cmd_id);
|
||||
nhs->group_management_new_key_cmd_id = 0;
|
||||
}
|
||||
|
||||
if (netdev->rekey_offload_cmd_id) {
|
||||
l_genl_family_cancel(nl80211, netdev->rekey_offload_cmd_id);
|
||||
netdev->rekey_offload_cmd_id = 0;
|
||||
}
|
||||
|
||||
netdev_rssi_polling_update(netdev);
|
||||
netdev_cqm_rssi_update(netdev);
|
||||
|
||||
if (netdev->sm) {
|
||||
eapol_sm_free(netdev->sm);
|
||||
netdev->sm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void netdev_ft_over_ds_auth_failed(struct netdev_ft_over_ds_info *info,
|
||||
uint16_t status)
|
||||
{
|
||||
l_queue_remove(info->netdev->ft_ds_list, info);
|
||||
ft_ds_info_free(&info->super);
|
||||
}
|
||||
|
||||
struct ft_ds_finder {
|
||||
const uint8_t *spa;
|
||||
const uint8_t *aa;
|
||||
};
|
||||
|
||||
static bool match_ft_ds_info(const void *a, const void *b)
|
||||
{
|
||||
const struct netdev_ft_over_ds_info *info = a;
|
||||
const struct ft_ds_finder *finder = b;
|
||||
|
||||
if (memcmp(info->super.spa, finder->spa, 6))
|
||||
return false;
|
||||
if (memcmp(info->super.aa, finder->aa, 6))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void netdev_ft_response_frame_event(const struct mmpdu_header *hdr,
|
||||
const void *body, size_t body_len,
|
||||
int rssi, void *user_data)
|
||||
@ -4685,181 +4519,6 @@ static void netdev_qos_map_frame_event(const struct mmpdu_header *hdr,
|
||||
netdev_send_qos_map_set(netdev, body + 4, body_len - 4);
|
||||
}
|
||||
|
||||
static bool netdev_ft_work_ready(struct wiphy_radio_work_item *item)
|
||||
{
|
||||
struct netdev *netdev = l_container_of(item, struct netdev, work);
|
||||
|
||||
if (!auth_proto_start(netdev->ap)) {
|
||||
/* Restore original nonce */
|
||||
memcpy(netdev->handshake->snonce, netdev->prev_snonce, 32);
|
||||
|
||||
netdev_connect_failed(netdev, NETDEV_RESULT_ABORTED,
|
||||
MMPDU_STATUS_CODE_UNSPECIFIED);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct wiphy_radio_work_item_ops ft_work_ops = {
|
||||
.do_work = netdev_ft_work_ready,
|
||||
};
|
||||
|
||||
int netdev_fast_transition(struct netdev *netdev,
|
||||
const struct scan_bss *target_bss,
|
||||
const struct scan_bss *orig_bss,
|
||||
netdev_connect_cb_t cb)
|
||||
{
|
||||
if (!netdev->operational)
|
||||
return -ENOTCONN;
|
||||
|
||||
if (!netdev->handshake->mde || !target_bss->mde_present ||
|
||||
l_get_le16(netdev->handshake->mde + 2) !=
|
||||
l_get_le16(target_bss->mde))
|
||||
return -EINVAL;
|
||||
|
||||
netdev->connect_cb = cb;
|
||||
|
||||
netdev->ap = ft_over_air_sm_new(netdev->handshake,
|
||||
netdev_ft_tx_authenticate,
|
||||
netdev_ft_tx_associate,
|
||||
netdev_get_oci, netdev);
|
||||
prepare_ft(netdev, target_bss);
|
||||
|
||||
handshake_state_new_snonce(netdev->handshake);
|
||||
|
||||
wiphy_radio_work_insert(netdev->wiphy, &netdev->work,
|
||||
WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int netdev_fast_transition_over_ds(struct netdev *netdev,
|
||||
const struct scan_bss *target_bss,
|
||||
const struct scan_bss *orig_bss,
|
||||
netdev_connect_cb_t cb)
|
||||
{
|
||||
struct netdev_ft_over_ds_info *info;
|
||||
struct ft_ds_finder finder;
|
||||
|
||||
if (!netdev->operational)
|
||||
return -ENOTCONN;
|
||||
|
||||
if (!netdev->handshake->mde || !target_bss->mde_present ||
|
||||
l_get_le16(netdev->handshake->mde + 2) !=
|
||||
l_get_le16(target_bss->mde))
|
||||
return -EINVAL;
|
||||
|
||||
finder.spa = netdev->addr;
|
||||
finder.aa = target_bss->addr;
|
||||
|
||||
info = l_queue_find(netdev->ft_ds_list, match_ft_ds_info, &finder);
|
||||
|
||||
if (!info || !info->parsed)
|
||||
return -ENOENT;
|
||||
|
||||
netdev->connect_cb = cb;
|
||||
|
||||
netdev->ap = ft_over_ds_sm_new(netdev->handshake,
|
||||
netdev_ft_tx_associate,
|
||||
netdev);
|
||||
prepare_ft(netdev, target_bss);
|
||||
|
||||
ft_over_ds_prepare_handshake(&info->super, netdev->handshake);
|
||||
|
||||
wiphy_radio_work_insert(netdev->wiphy, &netdev->work,
|
||||
WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void netdev_ft_request_cb(struct l_genl_msg *msg, void *user_data)
|
||||
{
|
||||
struct netdev_ft_over_ds_info *info = user_data;
|
||||
|
||||
if (l_genl_msg_get_error(msg) < 0) {
|
||||
l_error("Could not send CMD_FRAME for FT-over-DS");
|
||||
netdev_ft_over_ds_auth_failed(info,
|
||||
MMPDU_STATUS_CODE_UNSPECIFIED);
|
||||
}
|
||||
}
|
||||
|
||||
static void netdev_ft_ds_info_free(struct ft_ds_info *ft)
|
||||
{
|
||||
struct netdev_ft_over_ds_info *info = l_container_of(ft,
|
||||
struct netdev_ft_over_ds_info, super);
|
||||
|
||||
l_free(info);
|
||||
}
|
||||
|
||||
int netdev_fast_transition_over_ds_action(struct netdev *netdev,
|
||||
const struct scan_bss *target_bss)
|
||||
{
|
||||
struct netdev_ft_over_ds_info *info;
|
||||
uint8_t ft_req[14];
|
||||
struct handshake_state *hs = netdev->handshake;
|
||||
struct iovec iovs[5];
|
||||
uint8_t buf[512];
|
||||
size_t len;
|
||||
|
||||
if (!netdev->operational)
|
||||
return -ENOTCONN;
|
||||
|
||||
if (!netdev->handshake->mde || !target_bss->mde_present ||
|
||||
l_get_le16(netdev->handshake->mde + 2) !=
|
||||
l_get_le16(target_bss->mde))
|
||||
return -EINVAL;
|
||||
|
||||
l_debug("");
|
||||
|
||||
info = l_new(struct netdev_ft_over_ds_info, 1);
|
||||
info->netdev = netdev;
|
||||
|
||||
memcpy(info->super.spa, hs->spa, ETH_ALEN);
|
||||
memcpy(info->super.aa, target_bss->addr, ETH_ALEN);
|
||||
memcpy(info->super.mde, target_bss->mde, sizeof(info->super.mde));
|
||||
|
||||
if (target_bss->rsne)
|
||||
info->super.authenticator_ie = l_memdup(target_bss->rsne,
|
||||
target_bss->rsne[1] + 2);
|
||||
|
||||
l_getrandom(info->super.snonce, 32);
|
||||
info->super.free = netdev_ft_ds_info_free;
|
||||
|
||||
ft_req[0] = 6; /* FT category */
|
||||
ft_req[1] = 1; /* FT Request action */
|
||||
memcpy(ft_req + 2, netdev->addr, 6);
|
||||
memcpy(ft_req + 8, info->super.aa, 6);
|
||||
|
||||
iovs[0].iov_base = ft_req;
|
||||
iovs[0].iov_len = sizeof(ft_req);
|
||||
|
||||
if (!ft_build_authenticate_ies(hs, false, info->super.snonce,
|
||||
buf, &len))
|
||||
goto failed;
|
||||
|
||||
iovs[1].iov_base = buf;
|
||||
iovs[1].iov_len = len;
|
||||
|
||||
iovs[2].iov_base = NULL;
|
||||
|
||||
if (!netdev->ft_ds_list)
|
||||
netdev->ft_ds_list = l_queue_new();
|
||||
|
||||
l_queue_push_head(netdev->ft_ds_list, info);
|
||||
|
||||
netdev_send_action_framev(netdev, netdev->handshake->aa, iovs, 2,
|
||||
netdev->frequency,
|
||||
netdev_ft_request_cb,
|
||||
info);
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
l_free(info);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static void netdev_preauth_cb(const uint8_t *pmk, void *user_data)
|
||||
{
|
||||
struct netdev_preauth_state *preauth = user_data;
|
||||
|
11
src/netdev.h
11
src/netdev.h
@ -166,16 +166,7 @@ int netdev_reassociate(struct netdev *netdev,
|
||||
struct handshake_state *hs,
|
||||
netdev_event_func_t event_filter,
|
||||
netdev_connect_cb_t cb, void *user_data);
|
||||
int netdev_fast_transition(struct netdev *netdev,
|
||||
const struct scan_bss *target_bss,
|
||||
const struct scan_bss *orig_bss,
|
||||
netdev_connect_cb_t cb);
|
||||
int netdev_fast_transition_over_ds_action(struct netdev *netdev,
|
||||
const struct scan_bss *target_bss);
|
||||
int netdev_fast_transition_over_ds(struct netdev *netdev,
|
||||
const struct scan_bss *target_bss,
|
||||
const struct scan_bss *orig_bss,
|
||||
netdev_connect_cb_t cb);
|
||||
|
||||
int netdev_preauthenticate(struct netdev *netdev,
|
||||
const struct scan_bss *target_bss,
|
||||
netdev_preauthenticate_cb_t cb,
|
||||
|
Loading…
Reference in New Issue
Block a user