aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/wext-compat.c
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/wext-compat.c
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/wext-compat.c')
-rw-r--r--net/wireless/wext-compat.c163
1 files changed, 101 insertions, 62 deletions
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