aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-07-08 08:22:54 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-24 15:05:09 -0400
commitfffd0934b9390f34bec45762192b7edd3b12b4b5 (patch)
treed9779803763261f5795fe39a402d79c4220a3a22 /net/wireless
parentb9454e83cac42fcdc90bfbfba479132bd6629455 (diff)
cfg80211: rework key operation
This reworks the key operation in cfg80211, and now only allows, from userspace, configuring keys (via nl80211) after the connection has been established (in managed mode), the IBSS been joined (in IBSS mode), at any time (in AP[_VLAN] modes) or never for all the other modes. In order to do shared key authentication correctly, it is now possible to give a WEP key to the AUTH command. To configure static WEP keys, these are given to the CONNECT or IBSS_JOIN command directly, for a userspace SME it is assumed it will configure it properly after the connection has been established. Since mac80211 used to check the default key in IBSS mode to see whether or not the network is protected, it needs an update in that area, as well as an update to make use of the WEP key passed to auth() for shared key authentication. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.c11
-rw-r--r--net/wireless/core.h32
-rw-r--r--net/wireless/ibss.c79
-rw-r--r--net/wireless/mlme.c16
-rw-r--r--net/wireless/nl80211.c170
-rw-r--r--net/wireless/sme.c97
-rw-r--r--net/wireless/util.c41
-rw-r--r--net/wireless/wext-compat.c163
-rw-r--r--net/wireless/wext-sme.c30
9 files changed, 495 insertions, 144 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 1a78b3c70cf2..97cc5968b7d6 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -666,14 +666,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
666 wdev_lock(wdev); 666 wdev_lock(wdev);
667 switch (wdev->iftype) { 667 switch (wdev->iftype) {
668 case NL80211_IFTYPE_ADHOC: 668 case NL80211_IFTYPE_ADHOC:
669 if (wdev->wext.ibss.ssid_len) 669 cfg80211_ibss_wext_join(rdev, wdev);
670 __cfg80211_join_ibss(rdev, dev,
671 &wdev->wext.ibss);
672 break; 670 break;
673 case NL80211_IFTYPE_STATION: 671 case NL80211_IFTYPE_STATION:
674 if (wdev->wext.connect.ssid_len) 672 cfg80211_mgd_wext_connect(rdev, wdev);
675 __cfg80211_connect(rdev, dev,
676 &wdev->wext.connect);
677 break; 673 break;
678 default: 674 default:
679 break; 675 break;
@@ -690,6 +686,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
690 } 686 }
691 mutex_unlock(&rdev->devlist_mtx); 687 mutex_unlock(&rdev->devlist_mtx);
692 mutex_destroy(&wdev->mtx); 688 mutex_destroy(&wdev->mtx);
689#ifdef CONFIG_WIRELESS_EXT
690 kfree(wdev->wext.keys);
691#endif
693 break; 692 break;
694 case NETDEV_PRE_UP: 693 case NETDEV_PRE_UP:
695 if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) 694 if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
diff --git a/net/wireless/core.h b/net/wireless/core.h
index e46cd6eb61d7..2ec8ddbe57de 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -238,6 +238,12 @@ struct cfg80211_event {
238 }; 238 };
239}; 239};
240 240
241struct cfg80211_cached_keys {
242 struct key_params params[6];
243 u8 data[6][WLAN_MAX_KEY_LEN];
244 int def, defmgmt;
245};
246
241 247
242/* free object */ 248/* free object */
243extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev); 249extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
@@ -256,14 +262,18 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
256/* IBSS */ 262/* IBSS */
257int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, 263int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
258 struct net_device *dev, 264 struct net_device *dev,
259 struct cfg80211_ibss_params *params); 265 struct cfg80211_ibss_params *params,
266 struct cfg80211_cached_keys *connkeys);
260int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, 267int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
261 struct net_device *dev, 268 struct net_device *dev,
262 struct cfg80211_ibss_params *params); 269 struct cfg80211_ibss_params *params,
270 struct cfg80211_cached_keys *connkeys);
263void cfg80211_clear_ibss(struct net_device *dev, bool nowext); 271void cfg80211_clear_ibss(struct net_device *dev, bool nowext);
264int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, 272int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
265 struct net_device *dev, bool nowext); 273 struct net_device *dev, bool nowext);
266void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid); 274void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid);
275int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
276 struct wireless_dev *wdev);
267 277
268/* MLME */ 278/* MLME */
269int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, 279int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
@@ -272,12 +282,14 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
272 enum nl80211_auth_type auth_type, 282 enum nl80211_auth_type auth_type,
273 const u8 *bssid, 283 const u8 *bssid,
274 const u8 *ssid, int ssid_len, 284 const u8 *ssid, int ssid_len,
275 const u8 *ie, int ie_len); 285 const u8 *ie, int ie_len,
286 const u8 *key, int key_len, int key_idx);
276int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, 287int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
277 struct net_device *dev, struct ieee80211_channel *chan, 288 struct net_device *dev, struct ieee80211_channel *chan,
278 enum nl80211_auth_type auth_type, const u8 *bssid, 289 enum nl80211_auth_type auth_type, const u8 *bssid,
279 const u8 *ssid, int ssid_len, 290 const u8 *ssid, int ssid_len,
280 const u8 *ie, int ie_len); 291 const u8 *ie, int ie_len,
292 const u8 *key, int key_len, int key_idx);
281int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, 293int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
282 struct net_device *dev, 294 struct net_device *dev,
283 struct ieee80211_channel *chan, 295 struct ieee80211_channel *chan,
@@ -310,10 +322,12 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
310/* SME */ 322/* SME */
311int __cfg80211_connect(struct cfg80211_registered_device *rdev, 323int __cfg80211_connect(struct cfg80211_registered_device *rdev,
312 struct net_device *dev, 324 struct net_device *dev,
313 struct cfg80211_connect_params *connect); 325 struct cfg80211_connect_params *connect,
326 struct cfg80211_cached_keys *connkeys);
314int cfg80211_connect(struct cfg80211_registered_device *rdev, 327int cfg80211_connect(struct cfg80211_registered_device *rdev,
315 struct net_device *dev, 328 struct net_device *dev,
316 struct cfg80211_connect_params *connect); 329 struct cfg80211_connect_params *connect,
330 struct cfg80211_cached_keys *connkeys);
317int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, 331int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
318 struct net_device *dev, u16 reason, 332 struct net_device *dev, u16 reason,
319 bool wextev); 333 bool wextev);
@@ -323,11 +337,14 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
323void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, 337void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
324 const u8 *req_ie, size_t req_ie_len, 338 const u8 *req_ie, size_t req_ie_len,
325 const u8 *resp_ie, size_t resp_ie_len); 339 const u8 *resp_ie, size_t resp_ie_len);
340int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
341 struct wireless_dev *wdev);
326 342
327void cfg80211_conn_work(struct work_struct *work); 343void cfg80211_conn_work(struct work_struct *work);
328 344
329/* internal helpers */ 345/* internal helpers */
330int cfg80211_validate_key_settings(struct key_params *params, int key_idx, 346int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
347 struct key_params *params, int key_idx,
331 const u8 *mac_addr); 348 const u8 *mac_addr);
332void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, 349void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
333 size_t ie_len, u16 reason, bool from_ap); 350 size_t ie_len, u16 reason, bool from_ap);
@@ -335,5 +352,6 @@ void cfg80211_sme_scan_done(struct net_device *dev);
335void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len); 352void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
336void cfg80211_sme_disassoc(struct net_device *dev, int idx); 353void cfg80211_sme_disassoc(struct net_device *dev, int idx);
337void __cfg80211_scan_done(struct work_struct *wk); 354void __cfg80211_scan_done(struct work_struct *wk);
355void cfg80211_upload_connect_keys(struct wireless_dev *wdev);
338 356
339#endif /* __NET_WIRELESS_CORE_H */ 357#endif /* __NET_WIRELESS_CORE_H */
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 99ef9364b7e8..9394e78cd11f 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -39,6 +39,8 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
39 cfg80211_hold_bss(bss_from_pub(bss)); 39 cfg80211_hold_bss(bss_from_pub(bss));
40 wdev->current_bss = bss_from_pub(bss); 40 wdev->current_bss = bss_from_pub(bss);
41 41
42 cfg80211_upload_connect_keys(wdev);
43
42 nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, 44 nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid,
43 GFP_KERNEL); 45 GFP_KERNEL);
44#ifdef CONFIG_WIRELESS_EXT 46#ifdef CONFIG_WIRELESS_EXT
@@ -71,7 +73,8 @@ EXPORT_SYMBOL(cfg80211_ibss_joined);
71 73
72int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, 74int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
73 struct net_device *dev, 75 struct net_device *dev,
74 struct cfg80211_ibss_params *params) 76 struct cfg80211_ibss_params *params,
77 struct cfg80211_cached_keys *connkeys)
75{ 78{
76 struct wireless_dev *wdev = dev->ieee80211_ptr; 79 struct wireless_dev *wdev = dev->ieee80211_ptr;
77 int err; 80 int err;
@@ -81,13 +84,18 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
81 if (wdev->ssid_len) 84 if (wdev->ssid_len)
82 return -EALREADY; 85 return -EALREADY;
83 86
87 if (WARN_ON(wdev->connect_keys))
88 kfree(wdev->connect_keys);
89 wdev->connect_keys = connkeys;
90
84#ifdef CONFIG_WIRELESS_EXT 91#ifdef CONFIG_WIRELESS_EXT
85 wdev->wext.ibss.channel = params->channel; 92 wdev->wext.ibss.channel = params->channel;
86#endif 93#endif
87 err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); 94 err = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
88 95 if (err) {
89 if (err) 96 wdev->connect_keys = NULL;
90 return err; 97 return err;
98 }
91 99
92 memcpy(wdev->ssid, params->ssid, params->ssid_len); 100 memcpy(wdev->ssid, params->ssid, params->ssid_len);
93 wdev->ssid_len = params->ssid_len; 101 wdev->ssid_len = params->ssid_len;
@@ -97,13 +105,14 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
97 105
98int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, 106int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
99 struct net_device *dev, 107 struct net_device *dev,
100 struct cfg80211_ibss_params *params) 108 struct cfg80211_ibss_params *params,
109 struct cfg80211_cached_keys *connkeys)
101{ 110{
102 struct wireless_dev *wdev = dev->ieee80211_ptr; 111 struct wireless_dev *wdev = dev->ieee80211_ptr;
103 int err; 112 int err;
104 113
105 wdev_lock(wdev); 114 wdev_lock(wdev);
106 err = __cfg80211_join_ibss(rdev, dev, params); 115 err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
107 wdev_unlock(wdev); 116 wdev_unlock(wdev);
108 117
109 return err; 118 return err;
@@ -112,9 +121,22 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
112static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) 121static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
113{ 122{
114 struct wireless_dev *wdev = dev->ieee80211_ptr; 123 struct wireless_dev *wdev = dev->ieee80211_ptr;
124 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
125 int i;
115 126
116 ASSERT_WDEV_LOCK(wdev); 127 ASSERT_WDEV_LOCK(wdev);
117 128
129 kfree(wdev->connect_keys);
130 wdev->connect_keys = NULL;
131
132 /*
133 * Delete all the keys ... pairwise keys can't really
134 * exist any more anyway, but default keys might.
135 */
136 if (rdev->ops->del_key)
137 for (i = 0; i < 6; i++)
138 rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
139
118 if (wdev->current_bss) { 140 if (wdev->current_bss) {
119 cfg80211_unhold_bss(wdev->current_bss); 141 cfg80211_unhold_bss(wdev->current_bss);
120 cfg80211_put_bss(&wdev->current_bss->pub); 142 cfg80211_put_bss(&wdev->current_bss->pub);
@@ -172,11 +194,14 @@ int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
172} 194}
173 195
174#ifdef CONFIG_WIRELESS_EXT 196#ifdef CONFIG_WIRELESS_EXT
175static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, 197int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
176 struct wireless_dev *wdev) 198 struct wireless_dev *wdev)
177{ 199{
200 struct cfg80211_cached_keys *ck = NULL;
178 enum ieee80211_band band; 201 enum ieee80211_band band;
179 int i; 202 int i, err;
203
204 ASSERT_WDEV_LOCK(wdev);
180 205
181 if (!wdev->wext.ibss.beacon_interval) 206 if (!wdev->wext.ibss.beacon_interval)
182 wdev->wext.ibss.beacon_interval = 100; 207 wdev->wext.ibss.beacon_interval = 100;
@@ -216,8 +241,24 @@ static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
216 if (!netif_running(wdev->netdev)) 241 if (!netif_running(wdev->netdev))
217 return 0; 242 return 0;
218 243
219 return cfg80211_join_ibss(wiphy_to_dev(wdev->wiphy), 244 if (wdev->wext.keys)
220 wdev->netdev, &wdev->wext.ibss); 245 wdev->wext.keys->def = wdev->wext.default_key;
246
247 wdev->wext.ibss.privacy = wdev->wext.default_key != -1;
248
249 if (wdev->wext.keys) {
250 ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL);
251 if (!ck)
252 return -ENOMEM;
253 for (i = 0; i < 6; i++)
254 ck->params[i].key = ck->data[i];
255 }
256 err = __cfg80211_join_ibss(rdev, wdev->netdev,
257 &wdev->wext.ibss, ck);
258 if (err)
259 kfree(ck);
260
261 return err;
221} 262}
222 263
223int cfg80211_ibss_wext_siwfreq(struct net_device *dev, 264int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
@@ -265,7 +306,11 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
265 wdev->wext.ibss.channel_fixed = false; 306 wdev->wext.ibss.channel_fixed = false;
266 } 307 }
267 308
268 return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); 309 wdev_lock(wdev);
310 err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
311 wdev_unlock(wdev);
312
313 return err;
269} 314}
270/* temporary symbol - mark GPL - in the future the handler won't be */ 315/* temporary symbol - mark GPL - in the future the handler won't be */
271EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwfreq); 316EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwfreq);
@@ -333,7 +378,11 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
333 memcpy(wdev->wext.ibss.ssid, ssid, len); 378 memcpy(wdev->wext.ibss.ssid, ssid, len);
334 wdev->wext.ibss.ssid_len = len; 379 wdev->wext.ibss.ssid_len = len;
335 380
336 return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); 381 wdev_lock(wdev);
382 err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
383 wdev_unlock(wdev);
384
385 return err;
337} 386}
338/* temporary symbol - mark GPL - in the future the handler won't be */ 387/* temporary symbol - mark GPL - in the future the handler won't be */
339EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwessid); 388EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwessid);
@@ -414,7 +463,11 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
414 } else 463 } else
415 wdev->wext.ibss.bssid = NULL; 464 wdev->wext.ibss.bssid = NULL;
416 465
417 return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); 466 wdev_lock(wdev);
467 err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
468 wdev_unlock(wdev);
469
470 return err;
418} 471}
419/* temporary symbol - mark GPL - in the future the handler won't be */ 472/* temporary symbol - mark GPL - in the future the handler won't be */
420EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwap); 473EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwap);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 1b2ca1fea7a1..8e4ce2fdf862 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -328,7 +328,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
328 enum nl80211_auth_type auth_type, 328 enum nl80211_auth_type auth_type,
329 const u8 *bssid, 329 const u8 *bssid,
330 const u8 *ssid, int ssid_len, 330 const u8 *ssid, int ssid_len,
331 const u8 *ie, int ie_len) 331 const u8 *ie, int ie_len,
332 const u8 *key, int key_len, int key_idx)
332{ 333{
333 struct wireless_dev *wdev = dev->ieee80211_ptr; 334 struct wireless_dev *wdev = dev->ieee80211_ptr;
334 struct cfg80211_auth_request req; 335 struct cfg80211_auth_request req;
@@ -337,6 +338,10 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
337 338
338 ASSERT_WDEV_LOCK(wdev); 339 ASSERT_WDEV_LOCK(wdev);
339 340
341 if (auth_type == NL80211_AUTHTYPE_SHARED_KEY)
342 if (!key || !key_len || key_idx < 0 || key_idx > 4)
343 return -EINVAL;
344
340 if (wdev->current_bss && 345 if (wdev->current_bss &&
341 memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) 346 memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0)
342 return -EALREADY; 347 return -EALREADY;
@@ -359,6 +364,9 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
359 req.auth_type = auth_type; 364 req.auth_type = auth_type;
360 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, 365 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
361 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); 366 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
367 req.key = key;
368 req.key_len = key_len;
369 req.key_idx = key_idx;
362 if (!req.bss) 370 if (!req.bss)
363 return -ENOENT; 371 return -ENOENT;
364 372
@@ -396,13 +404,15 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
396 struct net_device *dev, struct ieee80211_channel *chan, 404 struct net_device *dev, struct ieee80211_channel *chan,
397 enum nl80211_auth_type auth_type, const u8 *bssid, 405 enum nl80211_auth_type auth_type, const u8 *bssid,
398 const u8 *ssid, int ssid_len, 406 const u8 *ssid, int ssid_len,
399 const u8 *ie, int ie_len) 407 const u8 *ie, int ie_len,
408 const u8 *key, int key_len, int key_idx)
400{ 409{
401 int err; 410 int err;
402 411
403 wdev_lock(dev->ieee80211_ptr); 412 wdev_lock(dev->ieee80211_ptr);
404 err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, 413 err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
405 ssid, ssid_len, ie, ie_len); 414 ssid, ssid_len, ie, ie_len,
415 key, key_len, key_idx);
406 wdev_unlock(dev->ieee80211_ptr); 416 wdev_unlock(dev->ieee80211_ptr);
407 417
408 return err; 418 return err;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 50cf59316292..45c5f9c8e51b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -138,8 +138,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
138/* policy for the attributes */ 138/* policy for the attributes */
139static struct nla_policy 139static struct nla_policy
140nl80211_key_policy[NL80211_KEY_MAX + 1] __read_mostly = { 140nl80211_key_policy[NL80211_KEY_MAX + 1] __read_mostly = {
141 [NL80211_KEY_DATA] = { .type = NLA_BINARY, 141 [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
142 .len = WLAN_MAX_KEY_LEN },
143 [NL80211_KEY_IDX] = { .type = NLA_U8 }, 142 [NL80211_KEY_IDX] = { .type = NLA_U8 },
144 [NL80211_KEY_CIPHER] = { .type = NLA_U32 }, 143 [NL80211_KEY_CIPHER] = { .type = NLA_U32 },
145 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, 144 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
@@ -305,6 +304,83 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
305 return 0; 304 return 0;
306} 305}
307 306
307static struct cfg80211_cached_keys *
308nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
309 struct nlattr *keys)
310{
311 struct key_parse parse;
312 struct nlattr *key;
313 struct cfg80211_cached_keys *result;
314 int rem, err, def = 0;
315
316 result = kzalloc(sizeof(*result), GFP_KERNEL);
317 if (!result)
318 return ERR_PTR(-ENOMEM);
319
320 result->def = -1;
321 result->defmgmt = -1;
322
323 nla_for_each_nested(key, keys, rem) {
324 memset(&parse, 0, sizeof(parse));
325 parse.idx = -1;
326
327 err = nl80211_parse_key_new(key, &parse);
328 if (err)
329 goto error;
330 err = -EINVAL;
331 if (!parse.p.key)
332 goto error;
333 if (parse.idx < 0 || parse.idx > 4)
334 goto error;
335 if (parse.def) {
336 if (def)
337 goto error;
338 def = 1;
339 result->def = parse.idx;
340 } else if (parse.defmgmt)
341 goto error;
342 err = cfg80211_validate_key_settings(rdev, &parse.p,
343 parse.idx, NULL);
344 if (err)
345 goto error;
346 result->params[parse.idx].cipher = parse.p.cipher;
347 result->params[parse.idx].key_len = parse.p.key_len;
348 result->params[parse.idx].key = result->data[parse.idx];
349 memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
350 }
351
352 return result;
353 error:
354 kfree(result);
355 return ERR_PTR(err);
356}
357
358static int nl80211_key_allowed(struct wireless_dev *wdev)
359{
360 ASSERT_WDEV_LOCK(wdev);
361
362 if (!netif_running(wdev->netdev))
363 return -ENETDOWN;
364
365 switch (wdev->iftype) {
366 case NL80211_IFTYPE_AP:
367 case NL80211_IFTYPE_AP_VLAN:
368 break;
369 case NL80211_IFTYPE_ADHOC:
370 if (!wdev->current_bss)
371 return -ENOLINK;
372 break;
373 case NL80211_IFTYPE_STATION:
374 if (wdev->sme_state != CFG80211_SME_CONNECTED)
375 return -ENOLINK;
376 break;
377 default:
378 return -EINVAL;
379 }
380
381 return 0;
382}
383
308static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, 384static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
309 struct cfg80211_registered_device *dev) 385 struct cfg80211_registered_device *dev)
310{ 386{
@@ -1212,7 +1288,11 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1212 goto out; 1288 goto out;
1213 } 1289 }
1214 1290
1215 err = func(&rdev->wiphy, dev, key.idx); 1291 wdev_lock(dev->ieee80211_ptr);
1292 err = nl80211_key_allowed(dev->ieee80211_ptr);
1293 if (!err)
1294 err = func(&rdev->wiphy, dev, key.idx);
1295
1216#ifdef CONFIG_WIRELESS_EXT 1296#ifdef CONFIG_WIRELESS_EXT
1217 if (!err) { 1297 if (!err) {
1218 if (func == rdev->ops->set_default_key) 1298 if (func == rdev->ops->set_default_key)
@@ -1221,6 +1301,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1221 dev->ieee80211_ptr->wext.default_mgmt_key = key.idx; 1301 dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
1222 } 1302 }
1223#endif 1303#endif
1304 wdev_unlock(dev->ieee80211_ptr);
1224 1305
1225 out: 1306 out:
1226 cfg80211_unlock_rdev(rdev); 1307 cfg80211_unlock_rdev(rdev);
@@ -1235,7 +1316,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1235static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) 1316static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1236{ 1317{
1237 struct cfg80211_registered_device *rdev; 1318 struct cfg80211_registered_device *rdev;
1238 int err, i; 1319 int err;
1239 struct net_device *dev; 1320 struct net_device *dev;
1240 struct key_parse key; 1321 struct key_parse key;
1241 u8 *mac_addr = NULL; 1322 u8 *mac_addr = NULL;
@@ -1250,29 +1331,28 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1250 if (info->attrs[NL80211_ATTR_MAC]) 1331 if (info->attrs[NL80211_ATTR_MAC])
1251 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 1332 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1252 1333
1253 if (cfg80211_validate_key_settings(&key.p, key.idx, mac_addr))
1254 return -EINVAL;
1255
1256 rtnl_lock(); 1334 rtnl_lock();
1257 1335
1258 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); 1336 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
1259 if (err) 1337 if (err)
1260 goto unlock_rtnl; 1338 goto unlock_rtnl;
1261 1339
1262 for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) 1340 if (!rdev->ops->add_key) {
1263 if (key.p.cipher == rdev->wiphy.cipher_suites[i]) 1341 err = -EOPNOTSUPP;
1264 break;
1265 if (i == rdev->wiphy.n_cipher_suites) {
1266 err = -EINVAL;
1267 goto out; 1342 goto out;
1268 } 1343 }
1269 1344
1270 if (!rdev->ops->add_key) { 1345 if (cfg80211_validate_key_settings(rdev, &key.p, key.idx, mac_addr)) {
1271 err = -EOPNOTSUPP; 1346 err = -EINVAL;
1272 goto out; 1347 goto out;
1273 } 1348 }
1274 1349
1275 err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx, mac_addr, &key.p); 1350 wdev_lock(dev->ieee80211_ptr);
1351 err = nl80211_key_allowed(dev->ieee80211_ptr);
1352 if (!err)
1353 err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx,
1354 mac_addr, &key.p);
1355 wdev_unlock(dev->ieee80211_ptr);
1276 1356
1277 out: 1357 out:
1278 cfg80211_unlock_rdev(rdev); 1358 cfg80211_unlock_rdev(rdev);
@@ -1309,7 +1389,10 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1309 goto out; 1389 goto out;
1310 } 1390 }
1311 1391
1312 err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr); 1392 wdev_lock(dev->ieee80211_ptr);
1393 err = nl80211_key_allowed(dev->ieee80211_ptr);
1394 if (!err)
1395 err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr);
1313 1396
1314#ifdef CONFIG_WIRELESS_EXT 1397#ifdef CONFIG_WIRELESS_EXT
1315 if (!err) { 1398 if (!err) {
@@ -1319,6 +1402,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1319 dev->ieee80211_ptr->wext.default_mgmt_key = -1; 1402 dev->ieee80211_ptr->wext.default_mgmt_key = -1;
1320 } 1403 }
1321#endif 1404#endif
1405 wdev_unlock(dev->ieee80211_ptr);
1322 1406
1323 out: 1407 out:
1324 cfg80211_unlock_rdev(rdev); 1408 cfg80211_unlock_rdev(rdev);
@@ -3159,6 +3243,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3159 const u8 *bssid, *ssid, *ie = NULL; 3243 const u8 *bssid, *ssid, *ie = NULL;
3160 int err, ssid_len, ie_len = 0; 3244 int err, ssid_len, ie_len = 0;
3161 enum nl80211_auth_type auth_type; 3245 enum nl80211_auth_type auth_type;
3246 struct key_parse key;
3162 3247
3163 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 3248 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3164 return -EINVAL; 3249 return -EINVAL;
@@ -3175,6 +3260,25 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3175 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) 3260 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
3176 return -EINVAL; 3261 return -EINVAL;
3177 3262
3263 err = nl80211_parse_key(info, &key);
3264 if (err)
3265 return err;
3266
3267 if (key.idx >= 0) {
3268 if (!key.p.key || !key.p.key_len)
3269 return -EINVAL;
3270 if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 ||
3271 key.p.key_len != WLAN_KEY_LEN_WEP40) &&
3272 (key.p.cipher != WLAN_CIPHER_SUITE_WEP104 ||
3273 key.p.key_len != WLAN_KEY_LEN_WEP104))
3274 return -EINVAL;
3275 if (key.idx > 4)
3276 return -EINVAL;
3277 } else {
3278 key.p.key_len = 0;
3279 key.p.key = NULL;
3280 }
3281
3178 rtnl_lock(); 3282 rtnl_lock();
3179 3283
3180 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); 3284 err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
@@ -3219,7 +3323,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
3219 } 3323 }
3220 3324
3221 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, 3325 err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
3222 ssid, ssid_len, ie, ie_len); 3326 ssid, ssid_len, ie, ie_len,
3327 key.p.key, key.p.key_len, key.idx);
3223 3328
3224out: 3329out:
3225 cfg80211_unlock_rdev(rdev); 3330 cfg80211_unlock_rdev(rdev);
@@ -3506,6 +3611,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
3506 struct net_device *dev; 3611 struct net_device *dev;
3507 struct cfg80211_ibss_params ibss; 3612 struct cfg80211_ibss_params ibss;
3508 struct wiphy *wiphy; 3613 struct wiphy *wiphy;
3614 struct cfg80211_cached_keys *connkeys = NULL;
3509 int err; 3615 int err;
3510 3616
3511 memset(&ibss, 0, sizeof(ibss)); 3617 memset(&ibss, 0, sizeof(ibss));
@@ -3570,13 +3676,26 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
3570 } 3676 }
3571 3677
3572 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; 3678 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
3679 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
3680
3681 if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
3682 connkeys = nl80211_parse_connkeys(rdev,
3683 info->attrs[NL80211_ATTR_KEYS]);
3684 if (IS_ERR(connkeys)) {
3685 err = PTR_ERR(connkeys);
3686 connkeys = NULL;
3687 goto out;
3688 }
3689 }
3573 3690
3574 err = cfg80211_join_ibss(rdev, dev, &ibss); 3691 err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
3575 3692
3576out: 3693out:
3577 cfg80211_unlock_rdev(rdev); 3694 cfg80211_unlock_rdev(rdev);
3578 dev_put(dev); 3695 dev_put(dev);
3579unlock_rtnl: 3696unlock_rtnl:
3697 if (err)
3698 kfree(connkeys);
3580 rtnl_unlock(); 3699 rtnl_unlock();
3581 return err; 3700 return err;
3582} 3701}
@@ -3746,6 +3865,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
3746 struct net_device *dev; 3865 struct net_device *dev;
3747 struct cfg80211_connect_params connect; 3866 struct cfg80211_connect_params connect;
3748 struct wiphy *wiphy; 3867 struct wiphy *wiphy;
3868 struct cfg80211_cached_keys *connkeys = NULL;
3749 int err; 3869 int err;
3750 3870
3751 memset(&connect, 0, sizeof(connect)); 3871 memset(&connect, 0, sizeof(connect));
@@ -3810,12 +3930,24 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
3810 } 3930 }
3811 } 3931 }
3812 3932
3813 err = cfg80211_connect(rdev, dev, &connect); 3933 if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
3934 connkeys = nl80211_parse_connkeys(rdev,
3935 info->attrs[NL80211_ATTR_KEYS]);
3936 if (IS_ERR(connkeys)) {
3937 err = PTR_ERR(connkeys);
3938 connkeys = NULL;
3939 goto out;
3940 }
3941 }
3942
3943 err = cfg80211_connect(rdev, dev, &connect, connkeys);
3814 3944
3815out: 3945out:
3816 cfg80211_unlock_rdev(rdev); 3946 cfg80211_unlock_rdev(rdev);
3817 dev_put(dev); 3947 dev_put(dev);
3818unlock_rtnl: 3948unlock_rtnl:
3949 if (err)
3950 kfree(connkeys);
3819 rtnl_unlock(); 3951 rtnl_unlock();
3820 return err; 3952 return err;
3821} 3953}
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 79ca56cbfd36..d635a99dba51 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -125,7 +125,9 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
125 params->channel, params->auth_type, 125 params->channel, params->auth_type,
126 params->bssid, 126 params->bssid,
127 params->ssid, params->ssid_len, 127 params->ssid, params->ssid_len,
128 NULL, 0); 128 NULL, 0,
129 params->key, params->key_len,
130 params->key_idx);
129 case CFG80211_CONN_ASSOCIATE_NEXT: 131 case CFG80211_CONN_ASSOCIATE_NEXT:
130 BUG_ON(!rdev->ops->assoc); 132 BUG_ON(!rdev->ops->assoc);
131 wdev->conn->state = CFG80211_CONN_ASSOCIATING; 133 wdev->conn->state = CFG80211_CONN_ASSOCIATING;
@@ -279,8 +281,12 @@ void cfg80211_sme_rx_auth(struct net_device *dev,
279 /* select automatically between only open, shared, leap */ 281 /* select automatically between only open, shared, leap */
280 switch (wdev->conn->params.auth_type) { 282 switch (wdev->conn->params.auth_type) {
281 case NL80211_AUTHTYPE_OPEN_SYSTEM: 283 case NL80211_AUTHTYPE_OPEN_SYSTEM:
282 wdev->conn->params.auth_type = 284 if (wdev->connect_keys)
283 NL80211_AUTHTYPE_SHARED_KEY; 285 wdev->conn->params.auth_type =
286 NL80211_AUTHTYPE_SHARED_KEY;
287 else
288 wdev->conn->params.auth_type =
289 NL80211_AUTHTYPE_NETWORK_EAP;
284 break; 290 break;
285 case NL80211_AUTHTYPE_SHARED_KEY: 291 case NL80211_AUTHTYPE_SHARED_KEY:
286 wdev->conn->params.auth_type = 292 wdev->conn->params.auth_type =
@@ -353,10 +359,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
353#endif 359#endif
354 360
355 if (status == WLAN_STATUS_SUCCESS && 361 if (status == WLAN_STATUS_SUCCESS &&
356 wdev->sme_state == CFG80211_SME_IDLE) { 362 wdev->sme_state == CFG80211_SME_IDLE)
357 wdev->sme_state = CFG80211_SME_CONNECTED; 363 goto success;
358 return;
359 }
360 364
361 if (wdev->sme_state != CFG80211_SME_CONNECTING) 365 if (wdev->sme_state != CFG80211_SME_CONNECTING)
362 return; 366 return;
@@ -370,24 +374,29 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
370 if (wdev->conn) 374 if (wdev->conn)
371 wdev->conn->state = CFG80211_CONN_IDLE; 375 wdev->conn->state = CFG80211_CONN_IDLE;
372 376
373 if (status == WLAN_STATUS_SUCCESS) { 377 if (status != WLAN_STATUS_SUCCESS) {
374 bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
375 wdev->ssid, wdev->ssid_len,
376 WLAN_CAPABILITY_ESS,
377 WLAN_CAPABILITY_ESS);
378
379 if (WARN_ON(!bss))
380 return;
381
382 cfg80211_hold_bss(bss_from_pub(bss));
383 wdev->current_bss = bss_from_pub(bss);
384
385 wdev->sme_state = CFG80211_SME_CONNECTED;
386 } else {
387 wdev->sme_state = CFG80211_SME_IDLE; 378 wdev->sme_state = CFG80211_SME_IDLE;
388 kfree(wdev->conn); 379 kfree(wdev->conn);
389 wdev->conn = NULL; 380 wdev->conn = NULL;
381 kfree(wdev->connect_keys);
382 wdev->connect_keys = NULL;
383 return;
390 } 384 }
385
386 bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
387 wdev->ssid, wdev->ssid_len,
388 WLAN_CAPABILITY_ESS,
389 WLAN_CAPABILITY_ESS);
390
391 if (WARN_ON(!bss))
392 return;
393
394 cfg80211_hold_bss(bss_from_pub(bss));
395 wdev->current_bss = bss_from_pub(bss);
396
397 success:
398 wdev->sme_state = CFG80211_SME_CONNECTED;
399 cfg80211_upload_connect_keys(wdev);
391} 400}
392 401
393void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, 402void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
@@ -516,6 +525,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
516 size_t ie_len, u16 reason, bool from_ap) 525 size_t ie_len, u16 reason, bool from_ap)
517{ 526{
518 struct wireless_dev *wdev = dev->ieee80211_ptr; 527 struct wireless_dev *wdev = dev->ieee80211_ptr;
528 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
529 int i;
519#ifdef CONFIG_WIRELESS_EXT 530#ifdef CONFIG_WIRELESS_EXT
520 union iwreq_data wrqu; 531 union iwreq_data wrqu;
521#endif 532#endif
@@ -543,8 +554,15 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
543 wdev->conn = NULL; 554 wdev->conn = NULL;
544 } 555 }
545 556
546 nl80211_send_disconnected(wiphy_to_dev(wdev->wiphy), dev, 557 nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
547 reason, ie, ie_len, from_ap); 558
559 /*
560 * Delete all the keys ... pairwise keys can't really
561 * exist any more anyway, but default keys might.
562 */
563 if (rdev->ops->del_key)
564 for (i = 0; i < 6; i++)
565 rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
548 566
549#ifdef CONFIG_WIRELESS_EXT 567#ifdef CONFIG_WIRELESS_EXT
550 memset(&wrqu, 0, sizeof(wrqu)); 568 memset(&wrqu, 0, sizeof(wrqu));
@@ -580,7 +598,8 @@ EXPORT_SYMBOL(cfg80211_disconnected);
580 598
581int __cfg80211_connect(struct cfg80211_registered_device *rdev, 599int __cfg80211_connect(struct cfg80211_registered_device *rdev,
582 struct net_device *dev, 600 struct net_device *dev,
583 struct cfg80211_connect_params *connect) 601 struct cfg80211_connect_params *connect,
602 struct cfg80211_cached_keys *connkeys)
584{ 603{
585 struct wireless_dev *wdev = dev->ieee80211_ptr; 604 struct wireless_dev *wdev = dev->ieee80211_ptr;
586 int err; 605 int err;
@@ -590,6 +609,24 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
590 if (wdev->sme_state != CFG80211_SME_IDLE) 609 if (wdev->sme_state != CFG80211_SME_IDLE)
591 return -EALREADY; 610 return -EALREADY;
592 611
612 if (WARN_ON(wdev->connect_keys)) {
613 kfree(wdev->connect_keys);
614 wdev->connect_keys = NULL;
615 }
616
617 if (connkeys && connkeys->def >= 0) {
618 int idx;
619
620 idx = connkeys->def;
621 /* If given a WEP key we may need it for shared key auth */
622 if (connkeys->params[idx].cipher == WLAN_CIPHER_SUITE_WEP40 ||
623 connkeys->params[idx].cipher == WLAN_CIPHER_SUITE_WEP104) {
624 connect->key_idx = idx;
625 connect->key = connkeys->params[idx].key;
626 connect->key_len = connkeys->params[idx].key_len;
627 }
628 }
629
593 if (!rdev->ops->connect) { 630 if (!rdev->ops->connect) {
594 if (!rdev->ops->auth || !rdev->ops->assoc) 631 if (!rdev->ops->auth || !rdev->ops->assoc)
595 return -EOPNOTSUPP; 632 return -EOPNOTSUPP;
@@ -640,6 +677,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
640 cfg80211_get_conn_bss(wdev); 677 cfg80211_get_conn_bss(wdev);
641 678
642 wdev->sme_state = CFG80211_SME_CONNECTING; 679 wdev->sme_state = CFG80211_SME_CONNECTING;
680 wdev->connect_keys = connkeys;
643 681
644 /* we're good if we have both BSSID and channel */ 682 /* we're good if we have both BSSID and channel */
645 if (wdev->conn->params.bssid && wdev->conn->params.channel) { 683 if (wdev->conn->params.bssid && wdev->conn->params.channel) {
@@ -662,13 +700,16 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
662 kfree(wdev->conn); 700 kfree(wdev->conn);
663 wdev->conn = NULL; 701 wdev->conn = NULL;
664 wdev->sme_state = CFG80211_SME_IDLE; 702 wdev->sme_state = CFG80211_SME_IDLE;
703 wdev->connect_keys = NULL;
665 } 704 }
666 705
667 return err; 706 return err;
668 } else { 707 } else {
669 wdev->sme_state = CFG80211_SME_CONNECTING; 708 wdev->sme_state = CFG80211_SME_CONNECTING;
709 wdev->connect_keys = connkeys;
670 err = rdev->ops->connect(&rdev->wiphy, dev, connect); 710 err = rdev->ops->connect(&rdev->wiphy, dev, connect);
671 if (err) { 711 if (err) {
712 wdev->connect_keys = NULL;
672 wdev->sme_state = CFG80211_SME_IDLE; 713 wdev->sme_state = CFG80211_SME_IDLE;
673 return err; 714 return err;
674 } 715 }
@@ -682,12 +723,13 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
682 723
683int cfg80211_connect(struct cfg80211_registered_device *rdev, 724int cfg80211_connect(struct cfg80211_registered_device *rdev,
684 struct net_device *dev, 725 struct net_device *dev,
685 struct cfg80211_connect_params *connect) 726 struct cfg80211_connect_params *connect,
727 struct cfg80211_cached_keys *connkeys)
686{ 728{
687 int err; 729 int err;
688 730
689 wdev_lock(dev->ieee80211_ptr); 731 wdev_lock(dev->ieee80211_ptr);
690 err = __cfg80211_connect(rdev, dev, connect); 732 err = __cfg80211_connect(rdev, dev, connect, connkeys);
691 wdev_unlock(dev->ieee80211_ptr); 733 wdev_unlock(dev->ieee80211_ptr);
692 734
693 return err; 735 return err;
@@ -704,6 +746,9 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
704 if (wdev->sme_state == CFG80211_SME_IDLE) 746 if (wdev->sme_state == CFG80211_SME_IDLE)
705 return -EINVAL; 747 return -EINVAL;
706 748
749 kfree(wdev->connect_keys);
750 wdev->connect_keys = NULL;
751
707 if (!rdev->ops->disconnect) { 752 if (!rdev->ops->disconnect) {
708 if (!rdev->ops->deauth) 753 if (!rdev->ops->deauth)
709 return -EOPNOTSUPP; 754 return -EOPNOTSUPP;
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 28f8f96801d4..4bab380a1204 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -141,9 +141,12 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy)
141 set_mandatory_flags_band(wiphy->bands[band], band); 141 set_mandatory_flags_band(wiphy->bands[band], band);
142} 142}
143 143
144int cfg80211_validate_key_settings(struct key_params *params, int key_idx, 144int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
145 struct key_params *params, int key_idx,
145 const u8 *mac_addr) 146 const u8 *mac_addr)
146{ 147{
148 int i;
149
147 if (key_idx > 5) 150 if (key_idx > 5)
148 return -EINVAL; 151 return -EINVAL;
149 152
@@ -197,6 +200,12 @@ int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
197 } 200 }
198 } 201 }
199 202
203 for (i = 0; i < rdev->wiphy.n_cipher_suites; i++)
204 if (params->cipher == rdev->wiphy.cipher_suites[i])
205 break;
206 if (i == rdev->wiphy.n_cipher_suites)
207 return -EINVAL;
208
200 return 0; 209 return 0;
201} 210}
202 211
@@ -523,3 +532,33 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie)
523 return NULL; 532 return NULL;
524} 533}
525EXPORT_SYMBOL(ieee80211_bss_get_ie); 534EXPORT_SYMBOL(ieee80211_bss_get_ie);
535
536void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
537{
538 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
539 struct net_device *dev = wdev->netdev;
540 int i;
541
542 if (!wdev->connect_keys)
543 return;
544
545 for (i = 0; i < 6; i++) {
546 if (!wdev->connect_keys->params[i].cipher)
547 continue;
548 if (rdev->ops->add_key(wdev->wiphy, dev, i, NULL,
549 &wdev->connect_keys->params[i]))
550 printk(KERN_ERR "%s: failed to set key %d\n",
551 dev->name, i);
552 if (wdev->connect_keys->def == i)
553 if (rdev->ops->set_default_key(wdev->wiphy, dev, i))
554 printk(KERN_ERR "%s: failed to set defkey %d\n",
555 dev->name, i);
556 if (wdev->connect_keys->defmgmt == i)
557 if (rdev->ops->set_default_mgmt_key(wdev->wiphy, dev, i))
558 printk(KERN_ERR "%s: failed to set mgtdef %d\n",
559 dev->name, i);
560 }
561
562 kfree(wdev->connect_keys);
563 wdev->connect_keys = NULL;
564}
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 5088d89a30fc..5d0176338539 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -453,15 +453,32 @@ int cfg80211_wext_giwretry(struct net_device *dev,
453} 453}
454EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); 454EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry);
455 455
456static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, 456static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
457 struct net_device *dev, const u8 *addr, 457 struct net_device *dev, const u8 *addr,
458 bool remove, bool tx_key, int idx, 458 bool remove, bool tx_key, int idx,
459 struct key_params *params) 459 struct key_params *params)
460{ 460{
461 struct wireless_dev *wdev = dev->ieee80211_ptr; 461 struct wireless_dev *wdev = dev->ieee80211_ptr;
462 int err; 462 int err, i;
463
464 if (!wdev->wext.keys) {
465 wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
466 GFP_KERNEL);
467 if (!wdev->wext.keys)
468 return -ENOMEM;
469 for (i = 0; i < 6; i++)
470 wdev->wext.keys->params[i].key =
471 wdev->wext.keys->data[i];
472 }
473
474 if (wdev->iftype != NL80211_IFTYPE_ADHOC &&
475 wdev->iftype != NL80211_IFTYPE_STATION)
476 return -EOPNOTSUPP;
463 477
464 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { 478 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
479 if (!wdev->current_bss)
480 return -ENOLINK;
481
465 if (!rdev->ops->set_default_mgmt_key) 482 if (!rdev->ops->set_default_mgmt_key)
466 return -EOPNOTSUPP; 483 return -EOPNOTSUPP;
467 484
@@ -471,8 +488,14 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
471 return -EINVAL; 488 return -EINVAL;
472 489
473 if (remove) { 490 if (remove) {
474 err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); 491 err = 0;
492 if (wdev->current_bss)
493 err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
475 if (!err) { 494 if (!err) {
495 if (!addr) {
496 wdev->wext.keys->params[idx].key_len = 0;
497 wdev->wext.keys->params[idx].cipher = 0;
498 }
476 if (idx == wdev->wext.default_key) 499 if (idx == wdev->wext.default_key)
477 wdev->wext.default_key = -1; 500 wdev->wext.default_key = -1;
478 else if (idx == wdev->wext.default_mgmt_key) 501 else if (idx == wdev->wext.default_mgmt_key)
@@ -486,36 +509,64 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
486 return 0; 509 return 0;
487 510
488 return err; 511 return err;
489 } else { 512 }
490 if (addr)
491 tx_key = false;
492 513
493 if (cfg80211_validate_key_settings(params, idx, addr)) 514 if (addr)
494 return -EINVAL; 515 tx_key = false;
495 516
517 if (cfg80211_validate_key_settings(rdev, params, idx, addr))
518 return -EINVAL;
519
520 err = 0;
521 if (wdev->current_bss)
496 err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params); 522 err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params);
497 if (err) 523 if (err)
498 return err; 524 return err;
525
526 if (!addr) {
527 wdev->wext.keys->params[idx] = *params;
528 memcpy(wdev->wext.keys->data[idx],
529 params->key, params->key_len);
530 wdev->wext.keys->params[idx].key =
531 wdev->wext.keys->data[idx];
532 }
499 533
500 if (tx_key || (!addr && wdev->wext.default_key == -1)) { 534 if (params->cipher != WLAN_CIPHER_SUITE_AES_CMAC &&
535 (tx_key || (!addr && wdev->wext.default_key == -1))) {
536 if (wdev->current_bss)
501 err = rdev->ops->set_default_key(&rdev->wiphy, 537 err = rdev->ops->set_default_key(&rdev->wiphy,
502 dev, idx); 538 dev, idx);
503 if (!err) 539 if (!err)
504 wdev->wext.default_key = idx; 540 wdev->wext.default_key = idx;
505 return err; 541 return err;
506 } 542 }
507 543
508 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC && 544 if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
509 (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) { 545 (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
546 if (wdev->current_bss)
510 err = rdev->ops->set_default_mgmt_key(&rdev->wiphy, 547 err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
511 dev, idx); 548 dev, idx);
512 if (!err) 549 if (!err)
513 wdev->wext.default_mgmt_key = idx; 550 wdev->wext.default_mgmt_key = idx;
514 return err; 551 return err;
515 }
516
517 return 0;
518 } 552 }
553
554 return 0;
555}
556
557static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
558 struct net_device *dev, const u8 *addr,
559 bool remove, bool tx_key, int idx,
560 struct key_params *params)
561{
562 int err;
563
564 wdev_lock(dev->ieee80211_ptr);
565 err = __cfg80211_set_encryption(rdev, dev, addr, remove,
566 tx_key, idx, params);
567 wdev_unlock(dev->ieee80211_ptr);
568
569 return err;
519} 570}
520 571
521int cfg80211_wext_siwencode(struct net_device *dev, 572int cfg80211_wext_siwencode(struct net_device *dev,
@@ -528,6 +579,10 @@ int cfg80211_wext_siwencode(struct net_device *dev,
528 bool remove = false; 579 bool remove = false;
529 struct key_params params; 580 struct key_params params;
530 581
582 if (wdev->iftype != NL80211_IFTYPE_STATION &&
583 wdev->iftype != NL80211_IFTYPE_ADHOC)
584 return -EOPNOTSUPP;
585
531 /* no use -- only MFP (set_default_mgmt_key) is optional */ 586 /* no use -- only MFP (set_default_mgmt_key) is optional */
532 if (!rdev->ops->del_key || 587 if (!rdev->ops->del_key ||
533 !rdev->ops->add_key || 588 !rdev->ops->add_key ||
@@ -548,9 +603,14 @@ int cfg80211_wext_siwencode(struct net_device *dev,
548 remove = true; 603 remove = true;
549 else if (erq->length == 0) { 604 else if (erq->length == 0) {
550 /* No key data - just set the default TX key index */ 605 /* No key data - just set the default TX key index */
551 err = rdev->ops->set_default_key(&rdev->wiphy, dev, idx); 606 err = 0;
607 wdev_lock(wdev);
608 if (wdev->current_bss)
609 err = rdev->ops->set_default_key(&rdev->wiphy,
610 dev, idx);
552 if (!err) 611 if (!err)
553 wdev->wext.default_key = idx; 612 wdev->wext.default_key = idx;
613 wdev_unlock(wdev);
554 return err; 614 return err;
555 } 615 }
556 616
@@ -583,6 +643,10 @@ int cfg80211_wext_siwencodeext(struct net_device *dev,
583 struct key_params params; 643 struct key_params params;
584 u32 cipher; 644 u32 cipher;
585 645
646 if (wdev->iftype != NL80211_IFTYPE_STATION &&
647 wdev->iftype != NL80211_IFTYPE_ADHOC)
648 return -EOPNOTSUPP;
649
586 /* no use -- only MFP (set_default_mgmt_key) is optional */ 650 /* no use -- only MFP (set_default_mgmt_key) is optional */
587 if (!rdev->ops->del_key || 651 if (!rdev->ops->del_key ||
588 !rdev->ops->add_key || 652 !rdev->ops->add_key ||
@@ -656,37 +720,15 @@ int cfg80211_wext_siwencodeext(struct net_device *dev,
656} 720}
657EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext); 721EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext);
658 722
659struct giwencode_cookie {
660 size_t buflen;
661 char *keybuf;
662};
663
664static void giwencode_get_key_cb(void *cookie, struct key_params *params)
665{
666 struct giwencode_cookie *data = cookie;
667
668 if (!params->key) {
669 data->buflen = 0;
670 return;
671 }
672
673 data->buflen = min_t(size_t, data->buflen, params->key_len);
674 memcpy(data->keybuf, params->key, data->buflen);
675}
676
677int cfg80211_wext_giwencode(struct net_device *dev, 723int cfg80211_wext_giwencode(struct net_device *dev,
678 struct iw_request_info *info, 724 struct iw_request_info *info,
679 struct iw_point *erq, char *keybuf) 725 struct iw_point *erq, char *keybuf)
680{ 726{
681 struct wireless_dev *wdev = dev->ieee80211_ptr; 727 struct wireless_dev *wdev = dev->ieee80211_ptr;
682 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 728 int idx;
683 int idx, err;
684 struct giwencode_cookie data = {
685 .keybuf = keybuf,
686 .buflen = erq->length,
687 };
688 729
689 if (!rdev->ops->get_key) 730 if (wdev->iftype != NL80211_IFTYPE_STATION &&
731 wdev->iftype != NL80211_IFTYPE_ADHOC)
690 return -EOPNOTSUPP; 732 return -EOPNOTSUPP;
691 733
692 idx = erq->flags & IW_ENCODE_INDEX; 734 idx = erq->flags & IW_ENCODE_INDEX;
@@ -701,21 +743,18 @@ int cfg80211_wext_giwencode(struct net_device *dev,
701 743
702 erq->flags = idx + 1; 744 erq->flags = idx + 1;
703 745
704 err = rdev->ops->get_key(&rdev->wiphy, dev, idx, NULL, &data, 746 if (!wdev->wext.keys || !wdev->wext.keys->params[idx].cipher) {
705 giwencode_get_key_cb);
706 if (!err) {
707 erq->length = data.buflen;
708 erq->flags |= IW_ENCODE_ENABLED;
709 return 0;
710 }
711
712 if (err == -ENOENT) {
713 erq->flags |= IW_ENCODE_DISABLED; 747 erq->flags |= IW_ENCODE_DISABLED;
714 erq->length = 0; 748 erq->length = 0;
715 return 0; 749 return 0;
716 } 750 }
717 751
718 return err; 752 erq->length = min_t(size_t, erq->length,
753 wdev->wext.keys->params[idx].key_len);
754 memcpy(keybuf, wdev->wext.keys->params[idx].key, erq->length);
755 erq->flags |= IW_ENCODE_ENABLED;
756
757 return 0;
719} 758}
720EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode); 759EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
721 760
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index 6f75aaa7f795..c33ea9a5de78 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -10,10 +10,11 @@
10#include <net/cfg80211.h> 10#include <net/cfg80211.h>
11#include "nl80211.h" 11#include "nl80211.h"
12 12
13static int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, 13int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
14 struct wireless_dev *wdev) 14 struct wireless_dev *wdev)
15{ 15{
16 int err; 16 struct cfg80211_cached_keys *ck = NULL;
17 int err, i;
17 18
18 ASSERT_RDEV_LOCK(rdev); 19 ASSERT_RDEV_LOCK(rdev);
19 ASSERT_WDEV_LOCK(wdev); 20 ASSERT_WDEV_LOCK(wdev);
@@ -25,10 +26,25 @@ static int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
25 wdev->wext.connect.ie_len = wdev->wext.ie_len; 26 wdev->wext.connect.ie_len = wdev->wext.ie_len;
26 wdev->wext.connect.privacy = wdev->wext.default_key != -1; 27 wdev->wext.connect.privacy = wdev->wext.default_key != -1;
27 28
28 err = 0; 29 if (wdev->wext.keys) {
29 if (wdev->wext.connect.ssid_len != 0) 30 wdev->wext.keys->def = wdev->wext.default_key;
30 err = __cfg80211_connect(rdev, wdev->netdev, 31 wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
31 &wdev->wext.connect); 32 }
33
34 if (!wdev->wext.connect.ssid_len)
35 return 0;
36
37 if (wdev->wext.keys) {
38 ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL);
39 if (!ck)
40 return -ENOMEM;
41 for (i = 0; i < 6; i++)
42 ck->params[i].key = ck->data[i];
43 }
44 err = __cfg80211_connect(rdev, wdev->netdev,
45 &wdev->wext.connect, ck);
46 if (err)
47 kfree(ck);
32 48
33 return err; 49 return err;
34} 50}