Commit ff74c51e authored by Ilan Peer's avatar Ilan Peer Committed by Johannes Berg

cfg80211/mac80211: Allow user space to register for station Rx authentication

To support Pre Association Security Negotiation (PASN) while already
associated to one AP, allow user space to register to Rx
authentication frames, so that the user space logic would be able to
receive/handle authentication frames from a different AP as part of
PASN.

Note that it is expected that user space would intelligently register
for Rx authentication frames, i.e., only when PASN is used and
configure a match filter only for PASN authentication algorithm, as
otherwise the MLME functionality of mac80211 would be broken.

Additionally, since some versions of the user space daemons wrongly
register to all types of authentication frames (which might result in
unexpected behavior) allow such registration if the request is for a
specific authentication algorithm number.
Signed-off-by: default avatarIlan Peer <ilan.peer@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/20200131114529.894206-1-luca@coelho.fiSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent f93d6b21
...@@ -416,7 +416,20 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { ...@@ -416,7 +416,20 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
}, },
[NL80211_IFTYPE_STATION] = { [NL80211_IFTYPE_STATION] = {
.tx = 0xffff, .tx = 0xffff,
/*
* To support Pre Association Security Negotiation (PASN) while
* already associated to one AP, allow user space to register to
* Rx authentication frames, so that the user space logic would
* be able to receive/handle authentication frames from a
* different AP as part of PASN.
* It is expected that user space would intelligently register
* for Rx authentication frames, i.e., only when PASN is used
* and configure a match filter only for PASN authentication
* algorithm, as otherwise the MLME functionality of mac80211
* would be broken.
*/
.rx = BIT(IEEE80211_STYPE_ACTION >> 4) | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
BIT(IEEE80211_STYPE_AUTH >> 4) |
BIT(IEEE80211_STYPE_PROBE_REQ >> 4), BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
}, },
[NL80211_IFTYPE_AP] = { [NL80211_IFTYPE_AP] = {
......
...@@ -385,7 +385,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, ...@@ -385,7 +385,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
struct net_device *dev); struct net_device *dev);
int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid, int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
u16 frame_type, const u8 *match_data, u16 frame_type, const u8 *match_data,
int match_len); int match_len, struct netlink_ext_ack *extack);
void cfg80211_mlme_unreg_wk(struct work_struct *wk); void cfg80211_mlme_unreg_wk(struct work_struct *wk);
void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid); void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid);
void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev); void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* *
* Copyright (c) 2009, Jouni Malinen <j@w1.fi> * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2015 Intel Deutschland GmbH * Copyright (c) 2015 Intel Deutschland GmbH
* Copyright (C) 2019 Intel Corporation
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -470,7 +471,7 @@ void cfg80211_mlme_unreg_wk(struct work_struct *wk) ...@@ -470,7 +471,7 @@ void cfg80211_mlme_unreg_wk(struct work_struct *wk)
int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
u16 frame_type, const u8 *match_data, u16 frame_type, const u8 *match_data,
int match_len) int match_len, struct netlink_ext_ack *extack)
{ {
struct wiphy *wiphy = wdev->wiphy; struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
...@@ -481,15 +482,38 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, ...@@ -481,15 +482,38 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
if (!wdev->wiphy->mgmt_stypes) if (!wdev->wiphy->mgmt_stypes)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT) if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT) {
NL_SET_ERR_MSG(extack, "frame type not management");
return -EINVAL; return -EINVAL;
}
if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) {
NL_SET_ERR_MSG(extack, "Invalid frame type");
return -EINVAL; return -EINVAL;
}
mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4; mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type))) if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type))) {
NL_SET_ERR_MSG(extack,
"Registration to specific type not supported");
return -EINVAL;
}
/*
* To support Pre Association Security Negotiation (PASN), registration
* for authentication frames should be supported. However, as some
* versions of the user space daemons wrongly register to all types of
* authentication frames (which might result in unexpected behavior)
* allow such registration if the request is for a specific
* authentication algorithm number.
*/
if (wdev->iftype == NL80211_IFTYPE_STATION &&
(frame_type & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_AUTH &&
!(match_data && match_len >= 2)) {
NL_SET_ERR_MSG(extack,
"Authentication algorithm number required");
return -EINVAL; return -EINVAL;
}
nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL); nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL);
if (!nreg) if (!nreg)
...@@ -504,6 +528,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, ...@@ -504,6 +528,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
continue; continue;
if (memcmp(reg->match, match_data, mlen) == 0) { if (memcmp(reg->match, match_data, mlen) == 0) {
NL_SET_ERR_MSG(extack, "Match already configured");
err = -EALREADY; err = -EALREADY;
break; break;
} }
......
...@@ -10624,8 +10624,9 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) ...@@ -10624,8 +10624,9 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
return -EOPNOTSUPP; return -EOPNOTSUPP;
return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type, return cfg80211_mlme_register_mgmt(wdev, info->snd_portid, frame_type,
nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]),
info->extack);
} }
static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment