aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Drake <dsd@gentoo.org>2006-06-01 10:34:26 -0400
committerJohn W. Linville <linville@tuxdriver.com>2006-06-05 15:51:29 -0400
commit76ea4c7f4cd319dee35934ecab57745feae58fa5 (patch)
tree6151f9d89084a1e96f216a182ed3fc265dffd429
parent47fbe1bf3980b41d2e18e3774e8e1094f716d2d1 (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.h3
-rw-r--r--net/ieee80211/ieee80211_tx.c25
-rw-r--r--net/ieee80211/softmac/Kconfig1
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_auth.c12
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_io.c39
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);
1247extern int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev); 1247extern int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev);
1248extern void ieee80211_txb_free(struct ieee80211_txb *); 1248extern void ieee80211_txb_free(struct ieee80211_txb *);
1249extern int ieee80211_tx_frame(struct ieee80211_device *ieee, 1249extern 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 */
1253extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, 1254extern 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) */
557int ieee80211_tx_frame(struct ieee80211_device *ieee, 557int 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,
268static u32 268static u32
269ieee80211softmac_auth(struct ieee80211_auth **pkt, 269ieee80211softmac_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;