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/wireless/nl80211.c | |
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/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 60 |
1 files changed, 48 insertions, 12 deletions
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; |