diff options
author | Jouni Malinen <j@w1.fi> | 2012-09-30 12:29:39 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2012-10-17 05:02:11 -0400 |
commit | e39e5b5e7206767a0f1be0e5cb7acbd0db87ae60 (patch) | |
tree | e2c8641581e3ff336586bd08fbf978da72c9a514 /net | |
parent | 0f4126e8918985ccc1beb936efd4b9d1e9005a63 (diff) |
cfg80211: Allow user space to specify non-IEs to SAE Authentication
SAE extends Authentication frames with fields that are not information
elements. NL80211_ATTR_IE is not suitable for these, so introduce a new
attribute that can be used to specify the fields needed for SAE in
station mode.
Signed-off-by: Jouni Malinen <j@w1.fi>
[change to verify that SAE is only used with authenticate command]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/wireless/core.h | 6 | ||||
-rw-r--r-- | net/wireless/mlme.c | 11 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 60 | ||||
-rw-r--r-- | net/wireless/sme.c | 2 |
4 files changed, 61 insertions, 18 deletions
diff --git a/net/wireless/core.h b/net/wireless/core.h index a343be4a52bd..b8eb743fe7da 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -320,13 +320,15 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
320 | const u8 *bssid, | 320 | const u8 *bssid, |
321 | const u8 *ssid, int ssid_len, | 321 | const u8 *ssid, int ssid_len, |
322 | const u8 *ie, int ie_len, | 322 | const u8 *ie, int ie_len, |
323 | const u8 *key, int key_len, int key_idx); | 323 | const u8 *key, int key_len, int key_idx, |
324 | const u8 *sae_data, int sae_data_len); | ||
324 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | 325 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, |
325 | struct net_device *dev, struct ieee80211_channel *chan, | 326 | struct net_device *dev, struct ieee80211_channel *chan, |
326 | enum nl80211_auth_type auth_type, const u8 *bssid, | 327 | enum nl80211_auth_type auth_type, const u8 *bssid, |
327 | const u8 *ssid, int ssid_len, | 328 | const u8 *ssid, int ssid_len, |
328 | const u8 *ie, int ie_len, | 329 | const u8 *ie, int ie_len, |
329 | const u8 *key, int key_len, int key_idx); | 330 | const u8 *key, int key_len, int key_idx, |
331 | const u8 *sae_data, int sae_data_len); | ||
330 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 332 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
331 | struct net_device *dev, | 333 | struct net_device *dev, |
332 | struct ieee80211_channel *chan, | 334 | struct ieee80211_channel *chan, |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 8016fee0752b..460d49325741 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -273,7 +273,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
273 | const u8 *bssid, | 273 | const u8 *bssid, |
274 | const u8 *ssid, int ssid_len, | 274 | const u8 *ssid, int ssid_len, |
275 | const u8 *ie, int ie_len, | 275 | const u8 *ie, int ie_len, |
276 | const u8 *key, int key_len, int key_idx) | 276 | const u8 *key, int key_len, int key_idx, |
277 | const u8 *sae_data, int sae_data_len) | ||
277 | { | 278 | { |
278 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 279 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
279 | struct cfg80211_auth_request req; | 280 | struct cfg80211_auth_request req; |
@@ -293,6 +294,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
293 | 294 | ||
294 | req.ie = ie; | 295 | req.ie = ie; |
295 | req.ie_len = ie_len; | 296 | req.ie_len = ie_len; |
297 | req.sae_data = sae_data; | ||
298 | req.sae_data_len = sae_data_len; | ||
296 | req.auth_type = auth_type; | 299 | req.auth_type = auth_type; |
297 | req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, | 300 | req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, |
298 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | 301 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); |
@@ -319,7 +322,8 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
319 | enum nl80211_auth_type auth_type, const u8 *bssid, | 322 | enum nl80211_auth_type auth_type, const u8 *bssid, |
320 | const u8 *ssid, int ssid_len, | 323 | const u8 *ssid, int ssid_len, |
321 | const u8 *ie, int ie_len, | 324 | const u8 *ie, int ie_len, |
322 | const u8 *key, int key_len, int key_idx) | 325 | const u8 *key, int key_len, int key_idx, |
326 | const u8 *sae_data, int sae_data_len) | ||
323 | { | 327 | { |
324 | int err; | 328 | int err; |
325 | 329 | ||
@@ -327,7 +331,8 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
327 | wdev_lock(dev->ieee80211_ptr); | 331 | wdev_lock(dev->ieee80211_ptr); |
328 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 332 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
329 | ssid, ssid_len, ie, ie_len, | 333 | ssid, ssid_len, ie, ie_len, |
330 | key, key_len, key_idx); | 334 | key, key_len, key_idx, |
335 | sae_data, sae_data_len); | ||
331 | wdev_unlock(dev->ieee80211_ptr); | 336 | wdev_unlock(dev->ieee80211_ptr); |
332 | mutex_unlock(&rdev->devlist_mtx); | 337 | mutex_unlock(&rdev->devlist_mtx); |
333 | 338 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 0418a6d5c1a6..74d8123ada77 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "nl80211.h" | 23 | #include "nl80211.h" |
24 | #include "reg.h" | 24 | #include "reg.h" |
25 | 25 | ||
26 | static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type); | ||
27 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | 26 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, |
28 | struct genl_info *info, | 27 | struct genl_info *info, |
29 | struct cfg80211_crypto_settings *settings, | 28 | struct cfg80211_crypto_settings *settings, |
@@ -355,6 +354,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
355 | [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 }, | 354 | [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 }, |
356 | [NL80211_ATTR_WDEV] = { .type = NLA_U64 }, | 355 | [NL80211_ATTR_WDEV] = { .type = NLA_U64 }, |
357 | [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 }, | 356 | [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 }, |
357 | [NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, }, | ||
358 | }; | 358 | }; |
359 | 359 | ||
360 | /* policy for the key attributes */ | 360 | /* policy for the key attributes */ |
@@ -2490,6 +2490,30 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, | |||
2490 | return ret; | 2490 | return ret; |
2491 | } | 2491 | } |
2492 | 2492 | ||
2493 | static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev, | ||
2494 | enum nl80211_auth_type auth_type, | ||
2495 | enum nl80211_commands cmd) | ||
2496 | { | ||
2497 | if (auth_type > NL80211_AUTHTYPE_MAX) | ||
2498 | return false; | ||
2499 | |||
2500 | switch (cmd) { | ||
2501 | case NL80211_CMD_AUTHENTICATE: | ||
2502 | if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) && | ||
2503 | auth_type == NL80211_AUTHTYPE_SAE) | ||
2504 | return false; | ||
2505 | return true; | ||
2506 | case NL80211_CMD_CONNECT: | ||
2507 | case NL80211_CMD_START_AP: | ||
2508 | /* SAE not supported yet */ | ||
2509 | if (auth_type == NL80211_AUTHTYPE_SAE) | ||
2510 | return false; | ||
2511 | return true; | ||
2512 | default: | ||
2513 | return false; | ||
2514 | } | ||
2515 | } | ||
2516 | |||
2493 | static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | 2517 | static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) |
2494 | { | 2518 | { |
2495 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 2519 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
@@ -2559,7 +2583,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
2559 | if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { | 2583 | if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { |
2560 | params.auth_type = nla_get_u32( | 2584 | params.auth_type = nla_get_u32( |
2561 | info->attrs[NL80211_ATTR_AUTH_TYPE]); | 2585 | info->attrs[NL80211_ATTR_AUTH_TYPE]); |
2562 | if (!nl80211_valid_auth_type(params.auth_type)) | 2586 | if (!nl80211_valid_auth_type(rdev, params.auth_type, |
2587 | NL80211_CMD_START_AP)) | ||
2563 | return -EINVAL; | 2588 | return -EINVAL; |
2564 | } else | 2589 | } else |
2565 | params.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | 2590 | params.auth_type = NL80211_AUTHTYPE_AUTOMATIC; |
@@ -4852,11 +4877,6 @@ static int nl80211_dump_survey(struct sk_buff *skb, | |||
4852 | return res; | 4877 | return res; |
4853 | } | 4878 | } |
4854 | 4879 | ||
4855 | static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type) | ||
4856 | { | ||
4857 | return auth_type <= NL80211_AUTHTYPE_MAX; | ||
4858 | } | ||
4859 | |||
4860 | static bool nl80211_valid_wpa_versions(u32 wpa_versions) | 4880 | static bool nl80211_valid_wpa_versions(u32 wpa_versions) |
4861 | { | 4881 | { |
4862 | return !(wpa_versions & ~(NL80211_WPA_VERSION_1 | | 4882 | return !(wpa_versions & ~(NL80211_WPA_VERSION_1 | |
@@ -4868,8 +4888,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
4868 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 4888 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4869 | struct net_device *dev = info->user_ptr[1]; | 4889 | struct net_device *dev = info->user_ptr[1]; |
4870 | struct ieee80211_channel *chan; | 4890 | struct ieee80211_channel *chan; |
4871 | const u8 *bssid, *ssid, *ie = NULL; | 4891 | const u8 *bssid, *ssid, *ie = NULL, *sae_data = NULL; |
4872 | int err, ssid_len, ie_len = 0; | 4892 | int err, ssid_len, ie_len = 0, sae_data_len = 0; |
4873 | enum nl80211_auth_type auth_type; | 4893 | enum nl80211_auth_type auth_type; |
4874 | struct key_parse key; | 4894 | struct key_parse key; |
4875 | bool local_state_change; | 4895 | bool local_state_change; |
@@ -4945,9 +4965,23 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
4945 | } | 4965 | } |
4946 | 4966 | ||
4947 | auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); | 4967 | auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); |
4948 | if (!nl80211_valid_auth_type(auth_type)) | 4968 | if (!nl80211_valid_auth_type(rdev, auth_type, NL80211_CMD_AUTHENTICATE)) |
4949 | return -EINVAL; | 4969 | return -EINVAL; |
4950 | 4970 | ||
4971 | if (auth_type == NL80211_AUTHTYPE_SAE && | ||
4972 | !info->attrs[NL80211_ATTR_SAE_DATA]) | ||
4973 | return -EINVAL; | ||
4974 | |||
4975 | if (info->attrs[NL80211_ATTR_SAE_DATA]) { | ||
4976 | if (auth_type != NL80211_AUTHTYPE_SAE) | ||
4977 | return -EINVAL; | ||
4978 | sae_data = nla_data(info->attrs[NL80211_ATTR_SAE_DATA]); | ||
4979 | sae_data_len = nla_len(info->attrs[NL80211_ATTR_SAE_DATA]); | ||
4980 | /* need to include at least Auth Transaction and Status Code */ | ||
4981 | if (sae_data_len < 4) | ||
4982 | return -EINVAL; | ||
4983 | } | ||
4984 | |||
4951 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; | 4985 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; |
4952 | 4986 | ||
4953 | /* | 4987 | /* |
@@ -4959,7 +4993,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
4959 | 4993 | ||
4960 | return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 4994 | return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
4961 | ssid, ssid_len, ie, ie_len, | 4995 | ssid, ssid_len, ie, ie_len, |
4962 | key.p.key, key.p.key_len, key.idx); | 4996 | key.p.key, key.p.key_len, key.idx, |
4997 | sae_data, sae_data_len); | ||
4963 | } | 4998 | } |
4964 | 4999 | ||
4965 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | 5000 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, |
@@ -5596,7 +5631,8 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
5596 | if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { | 5631 | if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { |
5597 | connect.auth_type = | 5632 | connect.auth_type = |
5598 | nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); | 5633 | nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); |
5599 | if (!nl80211_valid_auth_type(connect.auth_type)) | 5634 | if (!nl80211_valid_auth_type(rdev, connect.auth_type, |
5635 | NL80211_CMD_CONNECT)) | ||
5600 | return -EINVAL; | 5636 | return -EINVAL; |
5601 | } else | 5637 | } else |
5602 | connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | 5638 | connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 6f39cb808302..055d59643616 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -179,7 +179,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
179 | params->ssid, params->ssid_len, | 179 | params->ssid, params->ssid_len, |
180 | NULL, 0, | 180 | NULL, 0, |
181 | params->key, params->key_len, | 181 | params->key, params->key_len, |
182 | params->key_idx); | 182 | params->key_idx, NULL, 0); |
183 | case CFG80211_CONN_ASSOCIATE_NEXT: | 183 | case CFG80211_CONN_ASSOCIATE_NEXT: |
184 | BUG_ON(!rdev->ops->assoc); | 184 | BUG_ON(!rdev->ops->assoc); |
185 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; | 185 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; |