diff options
author | Daniel Drake <dsd@gentoo.org> | 2006-06-01 10:34:26 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2006-06-05 15:51:29 -0400 |
commit | 76ea4c7f4cd319dee35934ecab57745feae58fa5 (patch) | |
tree | 6151f9d89084a1e96f216a182ed3fc265dffd429 | |
parent | 47fbe1bf3980b41d2e18e3774e8e1094f716d2d1 (diff) |
[PATCH] softmac: complete shared key authentication
This patch finishes of the partially-complete shared key authentication
implementation in softmac.
The complication here is that we need to encrypt a management frame during
the authentication process. I don't think there are any other scenarios where
this would have to happen.
To get around this without causing too many headaches, we decided to just use
software encryption for this frame. The softmac config option now selects
IEEE80211_CRYPT_WEP so that we can ensure this available. This also involved
a modification to some otherwise unused ieee80211 API.
Signed-off-by: Daniel Drake <dsd@gentoo.org>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | include/net/ieee80211.h | 3 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_tx.c | 25 | ||||
-rw-r--r-- | net/ieee80211/softmac/Kconfig | 1 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_auth.c | 12 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_io.c | 39 |
5 files changed, 51 insertions, 29 deletions
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index 293e920ca59d..d5147770ad47 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h | |||
@@ -1247,7 +1247,8 @@ extern int ieee80211_set_encryption(struct ieee80211_device *ieee); | |||
1247 | extern int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev); | 1247 | extern int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev); |
1248 | extern void ieee80211_txb_free(struct ieee80211_txb *); | 1248 | extern void ieee80211_txb_free(struct ieee80211_txb *); |
1249 | extern int ieee80211_tx_frame(struct ieee80211_device *ieee, | 1249 | extern int ieee80211_tx_frame(struct ieee80211_device *ieee, |
1250 | struct ieee80211_hdr *frame, int len); | 1250 | struct ieee80211_hdr *frame, int hdr_len, |
1251 | int total_len, int encrypt_mpdu); | ||
1251 | 1252 | ||
1252 | /* ieee80211_rx.c */ | 1253 | /* ieee80211_rx.c */ |
1253 | extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, | 1254 | extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, |
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index 233d527c6953..6a5de1b84459 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c | |||
@@ -555,7 +555,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | |||
555 | /* Incoming 802.11 strucure is converted to a TXB | 555 | /* Incoming 802.11 strucure is converted to a TXB |
556 | * a block of 802.11 fragment packets (stored as skbs) */ | 556 | * a block of 802.11 fragment packets (stored as skbs) */ |
557 | int ieee80211_tx_frame(struct ieee80211_device *ieee, | 557 | int ieee80211_tx_frame(struct ieee80211_device *ieee, |
558 | struct ieee80211_hdr *frame, int len) | 558 | struct ieee80211_hdr *frame, int hdr_len, int total_len, |
559 | int encrypt_mpdu) | ||
559 | { | 560 | { |
560 | struct ieee80211_txb *txb = NULL; | 561 | struct ieee80211_txb *txb = NULL; |
561 | unsigned long flags; | 562 | unsigned long flags; |
@@ -565,6 +566,9 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee, | |||
565 | 566 | ||
566 | spin_lock_irqsave(&ieee->lock, flags); | 567 | spin_lock_irqsave(&ieee->lock, flags); |
567 | 568 | ||
569 | if (encrypt_mpdu && !ieee->sec.encrypt) | ||
570 | encrypt_mpdu = 0; | ||
571 | |||
568 | /* If there is no driver handler to take the TXB, dont' bother | 572 | /* If there is no driver handler to take the TXB, dont' bother |
569 | * creating it... */ | 573 | * creating it... */ |
570 | if (!ieee->hard_start_xmit) { | 574 | if (!ieee->hard_start_xmit) { |
@@ -572,32 +576,41 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee, | |||
572 | goto success; | 576 | goto success; |
573 | } | 577 | } |
574 | 578 | ||
575 | if (unlikely(len < 24)) { | 579 | if (unlikely(total_len < 24)) { |
576 | printk(KERN_WARNING "%s: skb too small (%d).\n", | 580 | printk(KERN_WARNING "%s: skb too small (%d).\n", |
577 | ieee->dev->name, len); | 581 | ieee->dev->name, total_len); |
578 | goto success; | 582 | goto success; |
579 | } | 583 | } |
580 | 584 | ||
585 | if (encrypt_mpdu) | ||
586 | frame->frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | ||
587 | |||
581 | /* When we allocate the TXB we allocate enough space for the reserve | 588 | /* When we allocate the TXB we allocate enough space for the reserve |
582 | * and full fragment bytes (bytes_per_frag doesn't include prefix, | 589 | * and full fragment bytes (bytes_per_frag doesn't include prefix, |
583 | * postfix, header, FCS, etc.) */ | 590 | * postfix, header, FCS, etc.) */ |
584 | txb = ieee80211_alloc_txb(1, len, ieee->tx_headroom, GFP_ATOMIC); | 591 | txb = ieee80211_alloc_txb(1, total_len, ieee->tx_headroom, GFP_ATOMIC); |
585 | if (unlikely(!txb)) { | 592 | if (unlikely(!txb)) { |
586 | printk(KERN_WARNING "%s: Could not allocate TXB\n", | 593 | printk(KERN_WARNING "%s: Could not allocate TXB\n", |
587 | ieee->dev->name); | 594 | ieee->dev->name); |
588 | goto failed; | 595 | goto failed; |
589 | } | 596 | } |
590 | txb->encrypted = 0; | 597 | txb->encrypted = 0; |
591 | txb->payload_size = len; | 598 | txb->payload_size = total_len; |
592 | 599 | ||
593 | skb_frag = txb->fragments[0]; | 600 | skb_frag = txb->fragments[0]; |
594 | 601 | ||
595 | memcpy(skb_put(skb_frag, len), frame, len); | 602 | memcpy(skb_put(skb_frag, total_len), frame, total_len); |
596 | 603 | ||
597 | if (ieee->config & | 604 | if (ieee->config & |
598 | (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) | 605 | (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) |
599 | skb_put(skb_frag, 4); | 606 | skb_put(skb_frag, 4); |
600 | 607 | ||
608 | /* To avoid overcomplicating things, we do the corner-case frame | ||
609 | * encryption in software. The only real situation where encryption is | ||
610 | * needed here is during software-based shared key authentication. */ | ||
611 | if (encrypt_mpdu) | ||
612 | ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); | ||
613 | |||
601 | success: | 614 | success: |
602 | spin_unlock_irqrestore(&ieee->lock, flags); | 615 | spin_unlock_irqrestore(&ieee->lock, flags); |
603 | 616 | ||
diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig index f2a27cc6ecb1..2811651cb134 100644 --- a/net/ieee80211/softmac/Kconfig +++ b/net/ieee80211/softmac/Kconfig | |||
@@ -2,6 +2,7 @@ config IEEE80211_SOFTMAC | |||
2 | tristate "Software MAC add-on to the IEEE 802.11 networking stack" | 2 | tristate "Software MAC add-on to the IEEE 802.11 networking stack" |
3 | depends on IEEE80211 && EXPERIMENTAL | 3 | depends on IEEE80211 && EXPERIMENTAL |
4 | select WIRELESS_EXT | 4 | select WIRELESS_EXT |
5 | select IEEE80211_CRYPT_WEP | ||
5 | ---help--- | 6 | ---help--- |
6 | This option enables the hardware independent software MAC addon | 7 | This option enables the hardware independent software MAC addon |
7 | for the IEEE 802.11 networking stack. | 8 | for the IEEE 802.11 networking stack. |
diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c index 084b6211f293..90b8484e509b 100644 --- a/net/ieee80211/softmac/ieee80211softmac_auth.c +++ b/net/ieee80211/softmac/ieee80211softmac_auth.c | |||
@@ -107,6 +107,7 @@ ieee80211softmac_auth_queue(void *data) | |||
107 | printkl(KERN_WARNING PFX "Authentication timed out with "MAC_FMT"\n", MAC_ARG(net->bssid)); | 107 | printkl(KERN_WARNING PFX "Authentication timed out with "MAC_FMT"\n", MAC_ARG(net->bssid)); |
108 | /* Remove this item from the queue */ | 108 | /* Remove this item from the queue */ |
109 | spin_lock_irqsave(&mac->lock, flags); | 109 | spin_lock_irqsave(&mac->lock, flags); |
110 | net->authenticating = 0; | ||
110 | ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net); | 111 | ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net); |
111 | cancel_delayed_work(&auth->work); /* just to make sure... */ | 112 | cancel_delayed_work(&auth->work); /* just to make sure... */ |
112 | list_del(&auth->list); | 113 | list_del(&auth->list); |
@@ -212,13 +213,13 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) | |||
212 | aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; | 213 | aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; |
213 | spin_unlock_irqrestore(&mac->lock, flags); | 214 | spin_unlock_irqrestore(&mac->lock, flags); |
214 | 215 | ||
215 | /* Switch to correct channel for this network */ | 216 | /* Send our response */ |
216 | mac->set_channel(mac->dev, net->channel); | ||
217 | |||
218 | /* Send our response (How to encrypt?) */ | ||
219 | ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state); | 217 | ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state); |
220 | break; | 218 | return 0; |
221 | case IEEE80211SOFTMAC_AUTH_SHARED_PASS: | 219 | case IEEE80211SOFTMAC_AUTH_SHARED_PASS: |
220 | kfree(net->challenge); | ||
221 | net->challenge = NULL; | ||
222 | net->challenge_len = 0; | ||
222 | /* Check the status code of the response */ | 223 | /* Check the status code of the response */ |
223 | switch(auth->status) { | 224 | switch(auth->status) { |
224 | case WLAN_STATUS_SUCCESS: | 225 | case WLAN_STATUS_SUCCESS: |
@@ -229,6 +230,7 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) | |||
229 | spin_unlock_irqrestore(&mac->lock, flags); | 230 | spin_unlock_irqrestore(&mac->lock, flags); |
230 | printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n", | 231 | printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n", |
231 | MAC_ARG(net->bssid)); | 232 | MAC_ARG(net->bssid)); |
233 | ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net); | ||
232 | break; | 234 | break; |
233 | default: | 235 | default: |
234 | printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n", | 236 | printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n", |
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c index 7b9e78d39598..44f51175a2fc 100644 --- a/net/ieee80211/softmac/ieee80211softmac_io.c +++ b/net/ieee80211/softmac/ieee80211softmac_io.c | |||
@@ -268,26 +268,27 @@ ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt, | |||
268 | static u32 | 268 | static u32 |
269 | ieee80211softmac_auth(struct ieee80211_auth **pkt, | 269 | ieee80211softmac_auth(struct ieee80211_auth **pkt, |
270 | struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, | 270 | struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, |
271 | u16 transaction, u16 status) | 271 | u16 transaction, u16 status, int *encrypt_mpdu) |
272 | { | 272 | { |
273 | u8 *data; | 273 | u8 *data; |
274 | int auth_mode = mac->ieee->sec.auth_mode; | ||
275 | int is_shared_response = (auth_mode == WLAN_AUTH_SHARED_KEY | ||
276 | && transaction == IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE); | ||
277 | |||
274 | /* Allocate Packet */ | 278 | /* Allocate Packet */ |
275 | (*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt( | 279 | (*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt( |
276 | 2 + /* Auth Algorithm */ | 280 | 2 + /* Auth Algorithm */ |
277 | 2 + /* Auth Transaction Seq */ | 281 | 2 + /* Auth Transaction Seq */ |
278 | 2 + /* Status Code */ | 282 | 2 + /* Status Code */ |
279 | /* Challenge Text IE */ | 283 | /* Challenge Text IE */ |
280 | mac->ieee->open_wep ? 0 : | 284 | is_shared_response ? 0 : 1 + 1 + net->challenge_len |
281 | 1 + 1 + WLAN_AUTH_CHALLENGE_LEN | 285 | ); |
282 | ); | ||
283 | if (unlikely((*pkt) == NULL)) | 286 | if (unlikely((*pkt) == NULL)) |
284 | return 0; | 287 | return 0; |
285 | ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid); | 288 | ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid); |
286 | 289 | ||
287 | /* Algorithm */ | 290 | /* Algorithm */ |
288 | (*pkt)->algorithm = mac->ieee->open_wep ? | 291 | (*pkt)->algorithm = cpu_to_le16(auth_mode); |
289 | cpu_to_le16(WLAN_AUTH_OPEN) : | ||
290 | cpu_to_le16(WLAN_AUTH_SHARED_KEY); | ||
291 | /* Transaction */ | 292 | /* Transaction */ |
292 | (*pkt)->transaction = cpu_to_le16(transaction); | 293 | (*pkt)->transaction = cpu_to_le16(transaction); |
293 | /* Status */ | 294 | /* Status */ |
@@ -295,18 +296,20 @@ ieee80211softmac_auth(struct ieee80211_auth **pkt, | |||
295 | 296 | ||
296 | data = (u8 *)(*pkt)->info_element; | 297 | data = (u8 *)(*pkt)->info_element; |
297 | /* Challenge Text */ | 298 | /* Challenge Text */ |
298 | if(!mac->ieee->open_wep){ | 299 | if (is_shared_response) { |
299 | *data = MFIE_TYPE_CHALLENGE; | 300 | *data = MFIE_TYPE_CHALLENGE; |
300 | data++; | 301 | data++; |
301 | 302 | ||
302 | /* Copy the challenge in */ | 303 | /* Copy the challenge in */ |
303 | // *data = challenge length | 304 | *data = net->challenge_len; |
304 | // data += sizeof(u16); | 305 | data++; |
305 | // memcpy(data, challenge, challenge length); | 306 | memcpy(data, net->challenge, net->challenge_len); |
306 | // data += challenge length; | 307 | data += net->challenge_len; |
307 | 308 | ||
308 | /* Add the full size to the packet length */ | 309 | /* Make sure this frame gets encrypted with the shared key */ |
309 | } | 310 | *encrypt_mpdu = 1; |
311 | } else | ||
312 | *encrypt_mpdu = 0; | ||
310 | 313 | ||
311 | /* Return the packet size */ | 314 | /* Return the packet size */ |
312 | return (data - (u8 *)(*pkt)); | 315 | return (data - (u8 *)(*pkt)); |
@@ -396,6 +399,7 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, | |||
396 | { | 399 | { |
397 | void *pkt = NULL; | 400 | void *pkt = NULL; |
398 | u32 pkt_size = 0; | 401 | u32 pkt_size = 0; |
402 | int encrypt_mpdu = 0; | ||
399 | 403 | ||
400 | switch(type) { | 404 | switch(type) { |
401 | case IEEE80211_STYPE_ASSOC_REQ: | 405 | case IEEE80211_STYPE_ASSOC_REQ: |
@@ -405,7 +409,7 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, | |||
405 | pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg); | 409 | pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg); |
406 | break; | 410 | break; |
407 | case IEEE80211_STYPE_AUTH: | 411 | case IEEE80211_STYPE_AUTH: |
408 | pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16)); | 412 | pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16), &encrypt_mpdu); |
409 | break; | 413 | break; |
410 | case IEEE80211_STYPE_DISASSOC: | 414 | case IEEE80211_STYPE_DISASSOC: |
411 | case IEEE80211_STYPE_DEAUTH: | 415 | case IEEE80211_STYPE_DEAUTH: |
@@ -434,7 +438,8 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, | |||
434 | * or get rid of it alltogether? | 438 | * or get rid of it alltogether? |
435 | * Does this work for you now? | 439 | * Does this work for you now? |
436 | */ | 440 | */ |
437 | ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt, pkt_size); | 441 | ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt, |
442 | IEEE80211_3ADDR_LEN, pkt_size, encrypt_mpdu); | ||
438 | 443 | ||
439 | kfree(pkt); | 444 | kfree(pkt); |
440 | return 0; | 445 | return 0; |