aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c170
1 files changed, 151 insertions, 19 deletions
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}