Javier Cardona (7):
mac80211: Support RSN information element on mesh interfaces
mac80211: New constant definitions for SAE
mac80211: Let user space receive and send mesh auth/deauth frames
mac80211: Accept mesh auth frames before a peer link has been
established
nl80211: Let userspace set the authenticated flag for a mesh peer
mac80211: Parse RSN information element to determine if a peer needs
authentication
mac80211: Check auth status before attempting to establish a peer
link
include/linux/ieee80211.h | 19 +++++++++++++++++
include/linux/nl80211.h | 13 ++++++++++-
include/net/cfg80211.h | 4 +++
net/mac80211/cfg.c | 25 +++++++++++++++++++--
net/mac80211/ieee80211_i.h | 4 ++-
net/mac80211/main.c | 4 ++-
net/mac80211/mesh.c | 33 ++++++++++++++++++++++++++++-
net/mac80211/mesh.h | 2 +-
net/mac80211/mesh_plink.c | 15 +++++++++++-
net/mac80211/rx.c | 3 +-
net/mac80211/tx.c | 3 +-
net/mac80211/util.c | 49 ++++++++++++++++++++++++++++++++++++++++++-
net/wireless/nl80211.c | 16 +++++++++++++-
13 files changed, 175 insertions(+), 15 deletions(-)
From: Javier Cardona <[email protected]>
Signed-off-by: Javier Cardona <[email protected]>
Tested-by: Thomas Pedersen <[email protected]>
---
include/linux/ieee80211.h | 19 +++++++++++++++++
net/mac80211/ieee80211_i.h | 2 +-
net/mac80211/mesh.c | 26 ++++++++++++++++++++++-
net/mac80211/mesh.h | 2 +-
net/mac80211/mesh_plink.c | 8 ++++++-
net/mac80211/util.c | 49 ++++++++++++++++++++++++++++++++++++++++++-
6 files changed, 100 insertions(+), 6 deletions(-)
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 294169e..5253a01 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -593,6 +593,25 @@ struct ieee80211_tim_ie {
} __attribute__ ((packed));
/**
+ * struct ieee80211_rsn_ie
+ *
+ * This structure is used to parse a "Robust Security Network element". After
+ * parsing, the pointers will point to *_count number of elements (e.g. if
+ * p_cipher_count is 3, p_cipher_suites will point to 3 suites).
+ */
+struct ieee80211_rsn_ie {
+ u16 version;
+ u8 *g_cipher_suite;
+ u16 p_cipher_count;
+ u8 *p_cipher_suites;
+ u16 akm_count;
+ u8 *akm_suites;
+ u16 capa;
+ u16 pkmid_count;
+ u8 *pkmids;
+};
+
+/**
* struct ieee80211_meshconf_ie
*
* This structure refers to "Mesh Configuration information element"
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index fc27222..eb838e7 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -994,7 +994,7 @@ struct ieee802_11_elems {
u8 *ibss_params;
u8 *challenge;
u8 *wpa;
- u8 *rsn;
+ struct ieee80211_rsn_ie rsn;
u8 *erp_info;
u8 *ext_supp_rates;
u8 *wmm_info;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index c0635c5..ab5ff5c 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -58,6 +58,29 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
}
/**
+ * mesh_peer_supports_sae - inspect RSN IE to see if an mp can do SAE auth
+ *
+ * @ie: information elements of a management frame from the mesh peer
+ */
+bool mesh_peer_supports_sae(struct ieee802_11_elems *ie)
+{
+ int i;
+ u8 *akm;
+ u8 sae_akm_suite[4] = { 0x00, 0x0f, 0xac, 0x08 };
+
+ if (ie->rsn.akm_count && ie->rsn.akm_suites) {
+ akm = ie->rsn.akm_suites;
+ for (i = 0; i < ie->rsn.akm_count; i++) {
+ if (memcmp(akm, sae_akm_suite, 4) == 0)
+ return true;
+ akm += 4;
+ }
+ }
+ return false;
+}
+
+
+/**
* mesh_matches_local - check if the config of a mesh point matches ours
*
* @ie: information elements of a management frame from the mesh peer
@@ -595,7 +618,8 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
supp_rates = ieee80211_sta_get_rates(local, &elems, band);
mesh_neighbour_update(mgmt->sa, supp_rates, sdata,
- mesh_peer_accepts_plinks(&elems));
+ mesh_peer_accepts_plinks(&elems),
+ mesh_peer_supports_sae(&elems));
}
}
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index b99e230..6a81b35 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -226,7 +226,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata);
/* Mesh plinks */
void mesh_neighbour_update(u8 *hw_addr, u32 rates,
- struct ieee80211_sub_if_data *sdata, bool add);
+ struct ieee80211_sub_if_data *sdata, bool add, bool rsn_enbld);
bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie);
void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
void mesh_plink_broken(struct sta_info *sta);
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 44b5393..5a845fd 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -238,7 +238,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
}
void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata,
- bool peer_accepting_plinks)
+ bool peer_accepting_plinks, bool rsn_enabled)
{
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
@@ -252,6 +252,12 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data
sta = mesh_plink_alloc(sdata, hw_addr, rates);
if (!sta)
return;
+ if (!rsn_enabled) {
+ mpl_dbg("Mesh peer %pM needs no auth\n", sta->sta.addr);
+ set_sta_flags(sta, WLAN_STA_AUTH);
+ } else
+ mpl_dbg("Mesh peer %pM needs auth\n", sta->sta.addr);
+
if (sta_info_insert_rcu(sta)) {
rcu_read_unlock();
return;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 556647a..77d10d6 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -573,6 +573,52 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
ieee802_11_parse_elems_crc(start, len, elems, 0, 0);
}
+static int parse_rsn_elem(u8 *start, size_t len, struct ieee80211_rsn_ie *rsn)
+{
+ int len_so_far;
+ u8 *pos = start;
+
+ if (len < 2 || !start || !rsn)
+ return -1;
+
+ /* Version is the only mandatory field. The rest are optional */
+ rsn->version = le16_to_cpu(*(__le16 *) pos);
+ len_so_far = 2;
+ if (len < len_so_far + 4)
+ return len_so_far;
+ rsn->g_cipher_suite = &pos[len_so_far];
+ len_so_far += 4;
+ if (len < len_so_far + 6)
+ return len_so_far;
+ rsn->p_cipher_count = le16_to_cpu(*(__le16 *) &pos[len_so_far]);
+ rsn->p_cipher_suites = &pos[len_so_far + 2];
+ len_so_far += 2 + rsn->p_cipher_count * 4;
+ if (len < len_so_far + 2) {
+ if (len < len_so_far)
+ rsn->p_cipher_count = le16_to_cpu(0);
+ return len_so_far;
+ }
+ rsn->akm_count = le16_to_cpu(*(__le16 *) &pos[len_so_far]);
+ rsn->akm_suites = &pos[len_so_far + 2];
+ len_so_far += 2 + rsn->akm_count * 4;
+ if (len < len_so_far + 2) {
+ if (len < len_so_far)
+ rsn->akm_count = le16_to_cpu(0);
+ return len_so_far;
+ }
+ rsn->capa = le16_to_cpu(*(__le16 *) &pos[len_so_far]);
+ len_so_far += 2;
+ if (len < len_so_far + 2)
+ return len_so_far;
+ rsn->pkmid_count = le16_to_cpu(*(__le16 *) &pos[len_so_far]);
+ rsn->pkmids = &pos[len_so_far + 2];
+ len_so_far += 2 + rsn->pkmid_count * 16;
+ if (len < len_so_far)
+ rsn->pkmid_count = le16_to_cpu(*(__le16 *) 0);
+ return len_so_far;
+}
+
+
u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
struct ieee802_11_elems *elems,
u64 filter, u32 crc)
@@ -658,8 +704,7 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
}
break;
case WLAN_EID_RSN:
- elems->rsn = pos;
- elems->rsn_len = elen;
+ parse_rsn_elem(pos, elen, &elems->rsn);
break;
case WLAN_EID_ERP_INFO:
elems->erp_info = pos;
--
1.7.0.4
On Thu, 2011-03-03 at 19:11 -0800, Thomas Pedersen wrote:
> From: Javier Cardona <[email protected]>
[snip (maybe more changelog would be nice)]
So .. a more "traditional" approach, like we do in AP, would be to let
userspace manage the lifetime of STA entries in this case. In managed
mode, we don't, but there mac80211 currently handles the authentication.
I think you should explore doing mesh more like the AP case. OTOH, I
don't know how the managed case with SAE would work.
johannes
From: Javier Cardona <[email protected]>
Signed-off-by: Javier Cardona <[email protected]>
Tested-by: Thomas Pedersen <[email protected]>
---
include/linux/nl80211.h | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 4e0990b..6adaa58 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1817,6 +1817,7 @@ enum nl80211_bss_status {
* @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only)
* @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r)
* @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP)
+ * @NL80211_AUTHTYPE_SAE: Simultaneous Authentication of Equals
* @__NL80211_AUTHTYPE_NUM: internal
* @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
* @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
@@ -1828,6 +1829,7 @@ enum nl80211_auth_type {
NL80211_AUTHTYPE_SHARED_KEY,
NL80211_AUTHTYPE_FT,
NL80211_AUTHTYPE_NETWORK_EAP,
+ NL80211_AUTHTYPE_SAE,
/* keep last */
__NL80211_AUTHTYPE_NUM,
--
1.7.0.4
From: Javier Cardona <[email protected]>
Signed-off-by: Javier Cardona <[email protected]>
Tested-by: Thomas Pedersen <[email protected]>
---
net/mac80211/rx.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 5c1930b..fe0f1e3 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -502,7 +502,8 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
if (ieee80211_is_probe_req(hdr->frame_control) ||
ieee80211_is_probe_resp(hdr->frame_control) ||
- ieee80211_is_beacon(hdr->frame_control))
+ ieee80211_is_beacon(hdr->frame_control) ||
+ ieee80211_is_auth(hdr->frame_control))
return RX_CONTINUE;
return RX_DROP_MONITOR;
--
1.7.0.4
On Fri, Mar 4, 2011 at 3:37 AM, Johannes Berg <[email protected]> wrote:
> On Thu, 2011-03-03 at 19:11 -0800, Thomas Pedersen wrote:
>> From: Javier Cardona <[email protected]>
>
> [...]
>
> If you manage stations in userspace, then this code is unnecessary.
> That'd be a big win in my eyes. The only thing the kernel would need to
> know is not to create station entries, right?
If userspace manages only rsn mesh stations then we do still need
this. That would be my preference: only require an authentication
daemon if you intend to join a secure mesh. In the same way that you
can connect to an open AP without a daemon.
Would you object to this approach?
--
Javier Cardona
cozybit Inc.
http://www.cozybit.com
On Fri, Mar 4, 2011 at 3:36 AM, Johannes Berg <[email protected]> wrote:
> On Thu, 2011-03-03 at 19:11 -0800, Thomas Pedersen wrote:
>> From: Javier Cardona <[email protected]>
>
> [snip (maybe more changelog would be nice)]
>
> So .. a more "traditional" approach, like we do in AP, would be to let
> userspace manage the lifetime of STA entries in this case. In managed
> mode, we don't, but there mac80211 currently handles the authentication.
>
> I think you should explore doing mesh more like the AP case. OTOH, I
> don't know how the managed case with SAE would work.
I see. Instead of setting the AUTH flag, just create the station. We
would like to do this only for secure meshes, and continue letting the
kernel manage mesh peers for "open" meshes without the need of
userspace intervention. We can certainly do it like you suggest, yes.
--
Javier Cardona
cozybit Inc.
http://www.cozybit.com
On Fri, Mar 4, 2011 at 3:32 AM, Johannes Berg <[email protected]> wrote:
> On Thu, 2011-03-03 at 19:11 -0800, Thomas Pedersen wrote:
>
>> +++ b/include/linux/nl80211.h
>> @@ -1817,6 +1817,7 @@ enum nl80211_bss_status {
>> ? * @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only)
>> ? * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r)
>> ? * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP)
>> + * @NL80211_AUTHTYPE_SAE: Simultaneous Authentication of Equals
>> ? * @__NL80211_AUTHTYPE_NUM: internal
>> ? * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
>> ? * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
>
> I think some of the auth code in nl80211 or so needs to catch this.
> Maybe nl80211_valid_auth_type() wouldn't be the right place, but for now
> it doesn't look like we'd be able to support this in managed mode, yet
> it wouldn't get errors and at least in the cfg80211 SME fall back to
> using OPEN, which is no fun.
We'll withdraw this then, given that we are not using it for mesh either.
--
Javier Cardona
cozybit Inc.
http://www.cozybit.com
From: Javier Cardona <[email protected]>
Add RSN information element as a mesh setup parameter.
Signed-off-by: Javier Cardona <[email protected]>
Tested-by: Thomas Pedersen <[email protected]>
---
include/linux/nl80211.h | 4 ++++
include/net/cfg80211.h | 4 ++++
net/mac80211/cfg.c | 19 ++++++++++++++++---
net/mac80211/ieee80211_i.h | 2 ++
net/mac80211/mesh.c | 7 +++++++
net/mac80211/tx.c | 3 ++-
net/wireless/nl80211.c | 13 +++++++++++++
7 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 3002218..4e0990b 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1690,6 +1690,9 @@ enum nl80211_meshconf_params {
* element that vendors will use to identify the path selection methods and
* metrics in use.
*
+ * @NL80211_MESH_SETUP_RSN_IE: The Robust Security Network information element
+ * use to advertise security capabilities of this mesh network.
+ *
* @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number
* @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use
*/
@@ -1698,6 +1701,7 @@ enum nl80211_mesh_setup_params {
NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL,
NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC,
NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE,
+ NL80211_MESH_SETUP_RSN_IE,
/* keep last */
__NL80211_MESH_SETUP_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1ac5786..87c0bb6 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -656,6 +656,8 @@ struct mesh_config {
* @path_metric: which metric to use
* @vendor_ie: vendor information elements (optional)
* @vendor_ie_len: length of vendor information elements
+ * @rsn_ie: robust secure network information elements (for SAE)
+ * @rsn_ie_len: length of rsn_ie
*
* These parameters are fixed when the mesh is created.
*/
@@ -666,6 +668,8 @@ struct mesh_setup {
u8 path_metric;
const u8 *vendor_ie;
u8 vendor_ie_len;
+ const u8 *rsn_ie;
+ u8 rsn_ie_len;
};
/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7b701dc..9d64ed9 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1030,15 +1030,28 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
if (!new_ie)
return -ENOMEM;
}
+ ifmsh->vendor_ie = new_ie;
+ kfree(old_ie);
+
+ /* then allocate the new rsn information element */
+ new_ie = NULL;
+ old_ie = ifmsh->rsn_ie;
+
+ ifmsh->rsn_ie_len = setup->rsn_ie_len;
+ if (setup->rsn_ie_len) {
+ new_ie = kmemdup(setup->rsn_ie, setup->rsn_ie_len,
+ GFP_KERNEL);
+ if (!new_ie)
+ return -ENOMEM;
+ }
+ ifmsh->rsn_ie = new_ie;
+ kfree(old_ie);
/* now copy the rest of the setup parameters */
ifmsh->mesh_id_len = setup->mesh_id_len;
memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len);
ifmsh->mesh_pp_id = setup->path_sel_proto;
ifmsh->mesh_pm_id = setup->path_metric;
- ifmsh->vendor_ie = new_ie;
-
- kfree(old_ie);
return 0;
}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index a404017..fc27222 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -490,6 +490,8 @@ struct ieee80211_if_mesh {
bool accepting_plinks;
const u8 *vendor_ie;
u8 vendor_ie_len;
+ const u8 *rsn_ie;
+ u8 rsn_ie_len;
};
#ifdef CONFIG_MAC80211_MESH
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 2a57cc0..c0635c5 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -279,6 +279,13 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
*pos++ = 0x00;
+ if (sdata->u.mesh.rsn_ie) {
+ int len = sdata->u.mesh.rsn_ie_len;
+ const u8 *data = sdata->u.mesh.rsn_ie;
+ if (skb_tailroom(skb) > len)
+ memcpy(skb_put(skb, len), data, len);
+ }
+
if (sdata->u.mesh.vendor_ie) {
int len = sdata->u.mesh.vendor_ie_len;
const u8 *data = sdata->u.mesh.vendor_ie;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 081dcaf..38db05e 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2262,7 +2262,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
/* headroom, head length, tail length and maximum TIM length */
skb = dev_alloc_skb(local->tx_headroom + 400 +
- sdata->u.mesh.vendor_ie_len);
+ sdata->u.mesh.vendor_ie_len +
+ sdata->u.mesh.rsn_ie_len);
if (!skb)
goto out;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4ebce42..150e8ed 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2806,6 +2806,8 @@ static const struct nla_policy
[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE] = { .type = NLA_BINARY,
.len = IEEE80211_MAX_DATA_LEN },
+ [NL80211_MESH_SETUP_RSN_IE] = { .type = NLA_BINARY,
+ .len = IEEE80211_MAX_DATA_LEN },
};
static int nl80211_parse_mesh_config(struct genl_info *info,
@@ -2915,6 +2917,17 @@ static int nl80211_parse_mesh_setup(struct genl_info *info,
setup->vendor_ie_len = nla_len(ieattr);
}
+ if (tb[NL80211_MESH_SETUP_RSN_IE]) {
+ struct nlattr *ieattr = tb[NL80211_MESH_SETUP_RSN_IE];
+ u8 *eid = nla_data(ieattr);
+ if (eid[0] != WLAN_EID_RSN)
+ return -EINVAL;
+ if (!is_valid_ie_attr(ieattr))
+ return -EINVAL;
+ setup->rsn_ie = nla_data(ieattr);
+ setup->rsn_ie_len = nla_len(ieattr);
+ }
+
return 0;
}
--
1.7.0.4
Johannes,
On Fri, Mar 4, 2011 at 3:30 AM, Johannes Berg <[email protected]> wrote:
> On Thu, 2011-03-03 at 19:11 -0800, Thomas Pedersen wrote:
>
>> +++ b/include/net/cfg80211.h
>> @@ -656,6 +656,8 @@ struct mesh_config {
>> ? * @path_metric: which metric to use
>> ? * @vendor_ie: vendor information elements (optional)
>> ? * @vendor_ie_len: length of vendor information elements
>> + * @rsn_ie: robust secure network information elements (for SAE)
>> + * @rsn_ie_len: length of rsn_ie
>
> Is this really useful over just putting it into the vendor IE we already
> have? We already have code to split IEs properly (see ieee80211_ie_split
> etc in mac80211), so maybe there's no reason to add more API?
Ah, I see. No need for a new rsn_ie but just remove the "vendor_" prefix.
We'll do.
Javier
--
Javier Cardona
cozybit Inc.
http://www.cozybit.com
On Fri, 2011-03-04 at 11:06 -0800, Javier Cardona wrote:
> On Fri, Mar 4, 2011 at 3:37 AM, Johannes Berg <[email protected]> wrote:
> > On Thu, 2011-03-03 at 19:11 -0800, Thomas Pedersen wrote:
> >> From: Javier Cardona <[email protected]>
> >
> > [...]
> >
> > If you manage stations in userspace, then this code is unnecessary.
> > That'd be a big win in my eyes. The only thing the kernel would need to
> > know is not to create station entries, right?
>
> If userspace manages only rsn mesh stations then we do still need
> this. That would be my preference: only require an authentication
> daemon if you intend to join a secure mesh. In the same way that you
> can connect to an open AP without a daemon.
> Would you object to this approach?
No, I wouldn't, but I don't see why you'd still need this? I'm not sure
exactly how all this works, but conceptually, is there anything wrong
with this:
* when creating the mesh, you'd say "this is a secure mesh"
* when an auth frame is received, you just pass it to userspace, as you
already have
* userspace is responsible for adding/removing stations
* the kernel doesn't need to parse RSN since if it's a secure mesh it
will know because userspace said it was
Actually, looking at your patch in more detail, it would seem like it
allows somebody to hijack the mesh by pretending it is an open network.
If the RSN IE isn't present, mesh_neighbour_update() gets passed false
for the rsn_enabled parameter -- even if the mesh should be secure --
and then the peer would be allowed to join just because it said it
didn't support RSN. Surely in that case it shouldn't be allowed to join?
Maybe I'm not reading this correctly.
johannes
From: Javier Cardona <[email protected]>
Signed-off-by: Javier Cardona <[email protected]>
Tested-by: Thomas Pedersen <[email protected]>
---
net/mac80211/main.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 2543e48..bff7237 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -542,7 +542,9 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
},
[NL80211_IFTYPE_MESH_POINT] = {
.tx = 0xffff,
- .rx = BIT(IEEE80211_STYPE_ACTION >> 4),
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4) |
+ BIT(IEEE80211_STYPE_DEAUTH >> 4),
},
};
--
1.7.0.4
On Fri, Mar 4, 2011 at 11:18 AM, Johannes Berg
<[email protected]> wrote:
> On Fri, 2011-03-04 at 11:06 -0800, Javier Cardona wrote:
>> On Fri, Mar 4, 2011 at 3:37 AM, Johannes Berg <[email protected]> wrote:
>> > On Thu, 2011-03-03 at 19:11 -0800, Thomas Pedersen wrote:
>> >> From: Javier Cardona <[email protected]>
>> >
>> > [...]
>> >
>> > If you manage stations in userspace, then this code is unnecessary.
>> > That'd be a big win in my eyes. The only thing the kernel would need to
>> > know is not to create station entries, right?
>>
>> If userspace manages only rsn mesh stations then we do still need
>> this. ?That would be my preference: ?only require an authentication
>> daemon if you intend to join a secure mesh. ?In the same way that you
>> can connect to an open AP without a daemon.
>> Would you object to this approach?
>
> No, I wouldn't, but I don't see why you'd still need this? I'm not sure
> exactly how all this works, but conceptually, is there anything wrong
> with this:
> ?* when creating the mesh, you'd say "this is a secure mesh"
> ?* when an auth frame is received, you just pass it to userspace, as you
> ? already have
> ?* userspace is responsible for adding/removing stations
> ?* the kernel doesn't need to parse RSN since if it's a secure mesh it
> ? will know because userspace said it was
I thought the RSN parsing was required at least for the case where a
station is open and discovers another station. If the other station
wants security, we (the open mesh) should leave that station alone.
But I guess the same can be achieved by just detecting the presence of
an RSN IE without parsing it (there was logic for that already).
So, in summary, you are suggesting that we pass the kernel something
like dot11MeshSecurityActivated when joining the mesh, in addition to
the RSN IE. And use the presence of the RSN IE in received beacons to
determine if other nodes have their security activated or not.
> Actually, looking at your patch in more detail, it would seem like it
> allows somebody to hijack the mesh by pretending it is an open network.
> If the RSN IE isn't present, mesh_neighbour_update() gets passed false
> for the rsn_enabled parameter -- even if the mesh should be secure --
> and then the peer would be allowed to join just because it said it
> didn't support RSN. Surely in that case it shouldn't be allowed to join?
You are right. We would need to check if security is enabled before
creating a peer with no RSN info.
Thanks!
--
Javier Cardona
cozybit Inc.
http://www.cozybit.com
On Thu, 2011-03-03 at 19:11 -0800, Thomas Pedersen wrote:
> +++ b/include/net/cfg80211.h
> @@ -656,6 +656,8 @@ struct mesh_config {
> * @path_metric: which metric to use
> * @vendor_ie: vendor information elements (optional)
> * @vendor_ie_len: length of vendor information elements
> + * @rsn_ie: robust secure network information elements (for SAE)
> + * @rsn_ie_len: length of rsn_ie
Is this really useful over just putting it into the vendor IE we already
have? We already have code to split IEs properly (see ieee80211_ie_split
etc in mac80211), so maybe there's no reason to add more API?
johannes
On Fri, 2011-03-04 at 11:01 -0800, Javier Cardona wrote:
> On Fri, Mar 4, 2011 at 3:36 AM, Johannes Berg <[email protected]> wrote:
> > On Thu, 2011-03-03 at 19:11 -0800, Thomas Pedersen wrote:
> >> From: Javier Cardona <[email protected]>
> >
> > [snip (maybe more changelog would be nice)]
> >
> > So .. a more "traditional" approach, like we do in AP, would be to let
> > userspace manage the lifetime of STA entries in this case. In managed
> > mode, we don't, but there mac80211 currently handles the authentication.
> >
> > I think you should explore doing mesh more like the AP case. OTOH, I
> > don't know how the managed case with SAE would work.
>
> I see. Instead of setting the AUTH flag, just create the station. We
> would like to do this only for secure meshes, and continue letting the
> kernel manage mesh peers for "open" meshes without the need of
> userspace intervention.
Sure. I might argue that even in the "open" mesh case sometimes
userspace would like to manage it, so I wouldn't make it depend on a
"secure mesh" flag but rather on a "userspace manages peers" flag, but
from a programming POV those would be the same, just a bit differently
semantically.
OTOH, that might not work when the mesh isn't secure since then there's
no clear point like the auth handshake when the station needs to be
added? Not quite sure here.
johannes
On Thu, 2011-03-03 at 19:11 -0800, Thomas Pedersen wrote:
> From: Javier Cardona <[email protected]>
[...]
If you manage stations in userspace, then this code is unnecessary.
That'd be a big win in my eyes. The only thing the kernel would need to
know is not to create station entries, right?
johannes
On Fri, 2011-03-04 at 11:45 -0800, Javier Cardona wrote:
> I thought the RSN parsing was required at least for the case where a
> station is open and discovers another station. If the other station
> wants security, we (the open mesh) should leave that station alone.
> But I guess the same can be achieved by just detecting the presence of
> an RSN IE without parsing it (there was logic for that already).
Right.
> So, in summary, you are suggesting that we pass the kernel something
> like dot11MeshSecurityActivated when joining the mesh, in addition to
> the RSN IE. And use the presence of the RSN IE in received beacons to
> determine if other nodes have their security activated or not.
Yes.
> > Actually, looking at your patch in more detail, it would seem like it
> > allows somebody to hijack the mesh by pretending it is an open network.
> > If the RSN IE isn't present, mesh_neighbour_update() gets passed false
> > for the rsn_enabled parameter -- even if the mesh should be secure --
> > and then the peer would be allowed to join just because it said it
> > didn't support RSN. Surely in that case it shouldn't be allowed to join?
>
> You are right. We would need to check if security is enabled before
> creating a peer with no RSN info.
Right -- we just check our own dot11MeshSecurityActivated, and if so
never create a peer but let userspace handle it. And if that is false,
we create a peer if (and only if) it has no RSN information.
johannes
On Thu, 2011-03-03 at 19:11 -0800, Thomas Pedersen wrote:
> From: Javier Cardona <[email protected]>
And this patch would also not be necessary since there wouldn't be a
station entry to start with.
johannes
On Thu, 2011-03-03 at 19:11 -0800, Thomas Pedersen wrote:
> +++ b/include/linux/nl80211.h
> @@ -1817,6 +1817,7 @@ enum nl80211_bss_status {
> * @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only)
> * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r)
> * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP)
> + * @NL80211_AUTHTYPE_SAE: Simultaneous Authentication of Equals
> * @__NL80211_AUTHTYPE_NUM: internal
> * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
> * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
I think some of the auth code in nl80211 or so needs to catch this.
Maybe nl80211_valid_auth_type() wouldn't be the right place, but for now
it doesn't look like we'd be able to support this in managed mode, yet
it wouldn't get errors and at least in the cfg80211 SME fall back to
using OPEN, which is no fun.
johannes
From: Javier Cardona <[email protected]>
Signed-off-by: Javier Cardona <[email protected]>
Tested-by: Thomas Pedersen <[email protected]>
---
include/linux/nl80211.h | 7 ++++++-
net/mac80211/cfg.c | 6 ++++++
net/wireless/nl80211.c | 3 ++-
3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 6adaa58..209d10e 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1159,8 +1159,11 @@ enum nl80211_iftype {
/**
* enum nl80211_sta_flags - station flags
*
- * Station flags. When a station is added to an AP interface, it is
+ * Station flags. Stations added to an AP interface are
* assumed to be already associated (and hence authenticated.)
+ * Mesh peers are added when they are discovered and authenticated later,
+ * either by userspace (SAE authentication) or in the kernel (open
+ * authentication).
*
* @__NL80211_STA_FLAG_INVALID: attribute number 0 is reserved
* @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X)
@@ -1168,6 +1171,7 @@ enum nl80211_iftype {
* with short barker preamble
* @NL80211_STA_FLAG_WME: station is WME/QoS capable
* @NL80211_STA_FLAG_MFP: station uses management frame protection
+ * @NL80211_STA_FLAG_AUTHENTICATED: (mesh) station is authenticated
* @NL80211_STA_FLAG_MAX: highest station flag number currently defined
* @__NL80211_STA_FLAG_AFTER_LAST: internal use
*/
@@ -1177,6 +1181,7 @@ enum nl80211_sta_flags {
NL80211_STA_FLAG_SHORT_PREAMBLE,
NL80211_STA_FLAG_WME,
NL80211_STA_FLAG_MFP,
+ NL80211_STA_FLAG_AUTHENTICATED,
/* keep last */
__NL80211_STA_FLAG_AFTER_LAST,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 9d64ed9..a49fb0b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -675,6 +675,12 @@ static void sta_apply_parameters(struct ieee80211_local *local,
if (set & BIT(NL80211_STA_FLAG_MFP))
sta->flags |= WLAN_STA_MFP;
}
+
+ if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
+ sta->flags &= ~WLAN_STA_AUTH;
+ if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
+ sta->flags |= WLAN_STA_AUTH;
+ }
spin_unlock_irqrestore(&sta->flaglock, flags);
/*
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 150e8ed..52ab105 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2262,7 +2262,8 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
err = -EINVAL;
if (params.supported_rates)
err = -EINVAL;
- if (params.sta_flags_mask)
+ if (params.sta_flags_mask &
+ ~BIT(NL80211_STA_FLAG_AUTHENTICATED))
err = -EINVAL;
break;
default:
--
1.7.0.4
From: Javier Cardona <[email protected]>
Signed-off-by: Javier Cardona <[email protected]>
Tested-by: Thomas Pedersen <[email protected]>
---
net/mac80211/mesh_plink.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 5a845fd..a89a90e 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -378,6 +378,9 @@ int mesh_plink_open(struct sta_info *sta)
__le16 llid;
struct ieee80211_sub_if_data *sdata = sta->sdata;
+ if (!test_sta_flags(sta, WLAN_STA_AUTH))
+ return -EPERM;
+
spin_lock_bh(&sta->lock);
get_random_bytes(&llid, 2);
sta->llid = llid;
@@ -486,7 +489,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
return;
}
- if (sta && sta->plink_state == PLINK_BLOCKED) {
+ if (sta && (!test_sta_flags(sta, WLAN_STA_AUTH) ||
+ sta->plink_state == PLINK_BLOCKED)) {
+ mpl_dbg("Mesh plink: blocked or unauthenticated peer\n");
rcu_read_unlock();
return;
}
--
1.7.0.4