2 * 802.1x EAPOL to RADIUS proxy (Network Access Server)
7 * RFC 2284: PPP Extensible Authentication Protocol (EAP)
8 * RFC 2548: Microsoft Vendor-specific RADIUS Attributes
9 * RFC 2716: PPP EAP TLS Authentication Protocol
10 * RFC 2865: Remote Authentication Dial In User Service (RADIUS)
11 * RFC 2869: RADIUS Extensions
12 * RFC 3079: Deriving Keys for use with Microsoft Point-to-Point Encryption (MPPE)
13 * IEEE 802.1X RADIUS Usage Guidelines
14 * RADIUS Master Session Key Attribute
15 * Making IEEE 802.11 Networks Enterprise-Ready
16 * Recommendations for IEEE 802.11 Access Points
18 * Copyright (C) 2010, Broadcom Corporation
19 * All Rights Reserved.
21 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
22 * the contents of this file may not be disclosed to third parties, copied
23 * or duplicated in any form, in whole or in part, without the prior
24 * written permission of Broadcom Corporation.
26 * $Id: nas.c 241388 2011-02-18 03:33:22Z stakita $
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <sys/ioctl.h>
42 #include <netinet/in.h>
44 #include <net/if_arp.h>
45 #include <arpa/inet.h>
50 extern int gettimeofday(struct timeval
*tv
, struct timezone
*tz
);
55 #include <bcmendian.h>
57 #include <proto/ethernet.h>
58 #include <proto/eapol.h>
59 #include <proto/eap.h>
65 #include "nas_radius.h"
68 #include <bcmcrypto/md5.h>
69 #include <bcmcrypto/rc4.h>
72 #define CHECK_EAPOL_KEY(key) (((key) == EAPOL_WPA_KEY) || ((key) == EAPOL_WPA2_KEY))
74 #define CHECK_EAPOL_KEY(key) ((key) == EAPOL_WPA_KEY)
77 static void eapol_canned(nas_t
*nas
, nas_sta_t
*sta
, unsigned char code
,
79 static void eapol_dispatch_ex(nas_t
*nas
, eapol_header_t
*eapol
, int preauth
);
81 static void toss_sta(nas_t
*nas
, nas_sta_t
*sta
, int reason
, int driver_signal
);
84 send_identity_req(nas_t
*nas
, nas_sta_t
*sta
)
88 dbg(nas
, "send Identity Request");
89 memcpy(eapol
.eth
.ether_shost
, &sta
->ea
, ETHER_ADDR_LEN
);
90 memcpy(eapol
.eth
.ether_dhost
, &nas
->ea
, ETHER_ADDR_LEN
);
91 eapol
.eth
.ether_type
= HTON16(ETHER_TYPE_802_1X
);
92 eapol
.version
= sta
->eapol_version
;
93 eapol
.type
= EAPOL_START
;
95 eapol_dispatch(nas
, &eapol
);
99 cleanup_sta(nas_t
*nas
, nas_sta_t
*sta
, int reason
, int driver_signal
)
101 unsigned char toss
= 1;
103 char eabuf
[ETHER_ADDR_STR_LEN
];
107 dbg(nas
, "called with NULL STA ponter");
111 /* De-Authenticate supplicant only once, and ignore further
112 * response from supplicant. We put supplicant in DISCONNECTED
113 * state, till we either receive handshake from supplicant or the
114 * wds_td initiator timer expires, either of the events put
115 * supplicant sta back in START state.
116 * Cleanup of supplicant sta is not required in case of WDS,
117 * Because, Removing WDS config leades to rc restart anyway, which
118 * restarts the whole NAS story.
120 if ((nas
->flags
& NAS_FLAG_WDS
) && (nas
->flags
& NAS_FLAG_AUTHENTICATOR
)) {
121 if (!driver_signal
&& (sta
->suppl
.state
!= WPA_DISCONNECTED
))
122 sta
->suppl
.state
= WPA_DISCONNECTED
;
123 if (!driver_signal
&& (sta
->suppl
.state
== WPA_DISCONNECTED
))
125 /* Dont toss supplicant sta in case of WDS, the initiator
126 * timer will trigger fake assoc.
131 /* If this is because of a driver message, telling the driver again
132 * is unnecessary (and could loop).
134 if (!driver_signal
) {
135 dbg(nas
, "deauthenticating %s", ether_etoa((uchar
*)&sta
->ea
, eabuf
));
136 nas_deauthenticate(nas
, &sta
->ea
, reason
);
138 /* Be careful not to leak timer descriptors. */
142 /* Respect the PMK caching if the STA is associate and Authenticated with WPA2 AKM */
143 if ((sta
->mode
& WPA2
) && (sta
->pae
.state
== AUTHENTICATED
) && sta
->pae
.ssnto
) {
144 dbg(nas
, "keep STA %s", ether_etoa((uchar
*)&sta
->ea
, eabuf
));
145 sta
->suppl
.state
= WPA_PTKSTART
;
149 if (toss
) toss_sta(nas
, sta
, 0, 1);
153 /* Just clean up the STA */
156 toss_sta(nas_t
*nas
, nas_sta_t
*sta
, int reason
, int driver_signal
)
161 char eabuf
[ETHER_ADDR_STR_LEN
];
164 dbg(nas
, "called with NULL STA ponter");
167 /* If this is because of a driver message, telling the driver again
168 * is unnecessary (and could loop).
170 if (!driver_signal
) {
171 dbg(nas
, "deauthenticating %s", ether_etoa((uchar
*)&sta
->ea
, eabuf
));
172 nas_deauthenticate(nas
, &sta
->ea
, reason
);
174 /* Be careful not to leak timer descriptors. */
176 dbg(nas
, "cleanup STA %s", ether_etoa((uchar
*)&sta
->ea
, eabuf
));
177 /* Remove this one from its hashed list. */
178 hash
= pae_hash(&sta
->ea
);
179 sta_list
= nas
->sta_hashed
[hash
];
181 if (sta_list
== sta
) {
182 /* It was the head, so its next is the new head. */
183 nas
->sta_hashed
[hash
] = sta
->next
;
186 /* Find the one that points to it and change the pointer. */
187 while ((sta_list
!= NULL
) && (sta_list
->next
!= sta
))
188 sta_list
= sta_list
->next
;
189 if (sta_list
== NULL
) {
190 dbg(nas
, "sta %s not in hash list",
191 ether_etoa((uchar
*)&sta
->ea
, eabuf
));
193 sta_list
->next
= sta
->next
;
202 * Search for or create a STA struct.
203 * If `enter' is not set, do not create it when one is not found.
206 lookup_sta(nas_t
*nas
, struct ether_addr
*ea
, sta_lookup_mode_t mode
)
214 /* Search for entry in the hash table */
215 for (sta
= nas
->sta_hashed
[hash
];
216 sta
&& memcmp(&sta
->ea
, ea
, ETHER_ADDR_LEN
);
219 /* One second resolution is probably good enough. */
222 /* Allocate a new entry */
226 /* Don't make an unwanted entry. */
227 if (mode
== SEARCH_ONLY
)
231 for (i
= 0; i
< MAX_SUPPLICANTS
; i
++) {
232 if (!nas
->sta
[i
].used
)
234 else if (nas
->sta
[i
].last_use
< oldest
) {
235 oldest
= nas
->sta
[i
].last_use
;
240 if (i
< MAX_SUPPLICANTS
) {
242 } else if (old_idx
== -1) {
243 /* Full up with all the same timestamp?! Can
244 * this really happen?
248 /* Didn't find one unused, so age out LRU entry. */
249 sta
= &nas
->sta
[old_idx
];
250 toss_sta(nas
, sta
, DOT11_RC_BUSY
, 0);
253 if ((sta
!= NULL
) && (sta
->pae
.radius
.request
!= NULL
)) {
254 free(sta
->pae
.radius
.request
);
256 /* Initialize entry */
257 memset(sta
, 0, (sizeof(nas_sta_t
)));
258 memcpy(&sta
->ea
, ea
, ETHER_ADDR_LEN
);
261 /* initialize EAPOL version */
262 sta
->eapol_version
= WPA_EAPOL_VERSION
;
264 /* Initial STA state:
265 * Cheaper and harmless not to distiguish NAS mode.
267 if (nas
->flags
& NAS_FLAG_AUTHENTICATOR
)
268 sta
->suppl
.state
= sta
->suppl
.retry_state
= WPA_AUTHENTICATION2
;
270 if (nas
->flags
& NAS_FLAG_SUPPLICANT
)
271 sta
->suppl
.state
= sta
->suppl
.retry_state
= WPA_SUP_AUTHENTICATION
;
272 sta
->suppl
.pk_state
= EAPOL_SUP_PK_UNKNOWN
;
274 sta
->pae
.state
= INITIALIZE
;
276 /* initial mode/wsec/algom. assoc proc will override them */
277 if ((nas
->mode
& RADIUS
) && (nas
->wsec
& WEP_ENABLED
)) {
279 sta
->wsec
= WEP_ENABLED
;
280 sta
->algo
= CRYPTO_ALGO_WEP128
;
287 dbg(nas
, "mode %d wsec %d algo %d", sta
->mode
, sta
->wsec
, sta
->algo
);
289 /* Add entry to the cache */
290 sta
->next
= nas
->sta_hashed
[hash
];
291 nas
->sta_hashed
[hash
] = sta
;
298 /* Transition to new PAE state */
300 pae_state(nas_t
*nas
, nas_sta_t
*sta
, int state
)
303 char eabuf
[ETHER_ADDR_STR_LEN
];
305 sta
->pae
.state
= state
;
308 switch (sta
->pae
.state
) {
311 dbg(nas
, "Authenticated %s", ether_etoa((uchar
*)&sta
->ea
, eabuf
));
312 eapol_canned(nas
, sta
, EAP_SUCCESS
, 0);
318 dbg(nas
, "Held %s", ether_etoa((uchar
*)&sta
->ea
, eabuf
));
319 eapol_canned(nas
, sta
, EAP_FAILURE
, 0);
321 /* hold off for the quiet period */
322 sta
->quiet_while
= STA_QUIETWHILE_MAX
;
327 dbg(nas
, "Aborting %s", ether_etoa((uchar
*)&sta
->ea
, eabuf
));
328 if (sta
->pae
.radius
.username
.data
)
329 free(sta
->pae
.radius
.username
.data
);
330 memset(&sta
->pae
.radius
.username
, 0,
331 sizeof(sta
->pae
.radius
.username
));
332 if (sta
->pae
.radius
.state
.data
)
333 free(sta
->pae
.radius
.state
.data
);
334 memset(&sta
->pae
.radius
.state
, 0,
335 sizeof(sta
->pae
.radius
.state
));
336 if (sta
->pae
.radius
.request
)
337 free(sta
->pae
.radius
.request
);
338 sta
->pae
.radius
.request
= NULL
;
344 dbg(nas
, "Disconnected %s", ether_etoa((uchar
*)&sta
->ea
, eabuf
));
345 eapol_canned(nas
, sta
, EAP_FAILURE
, 0);
347 sta
->pae
.state
= CONNECTING
;
352 dbg(nas
, "Connecting %s", ether_etoa((uchar
*)&sta
->ea
, eabuf
));
353 sta
->pae
.flags
= 0; /* reset flags */
354 sta
->pae
.ssnto
= 0; /* session timeout */
355 eapol_canned(nas
, sta
, EAP_REQUEST
, EAP_IDENTITY
);
357 sta
->tx_when
= STA_TXPERIOD_MAX
;
361 dbg(nas
, "Authenticating %s", ether_etoa((uchar
*)&sta
->ea
, eabuf
));
362 sta
->auth_while
= STA_AUTHWHILE_MAX
;
366 dbg(nas
, "Unexpected state %d %s", sta
->pae
.state
,
367 ether_etoa((uchar
*)&sta
->ea
, eabuf
));
373 fix_wpa(nas_t
*nas
, nas_sta_t
*sta
, char *key
, int len
)
375 eapol_header_t eapol
;
376 eapol_wpa_key_header_t wpa_key
;
377 unsigned char buffer
[sizeof(eapol
) + sizeof(wpa_key
)];
378 wpa_t
*wpa
= (wpa_t
*)nas
->wpa
;
380 dbg(nas
, "use MPPE recv key as PMK");
381 /* Use the RADIUS key for a PMK. */
384 memcpy(sta
->suppl
.pmk
, key
, len
);
385 sta
->suppl
.pmk_len
= len
;
388 if (sta
->mode
& WPA2
) {
389 nas_wpa_calc_pmkid(wpa
, sta
);
390 if (sta
->flags
& STA_FLAG_PRE_AUTH
) {
391 /* Once Pre authed don't worry about this variable */
392 sta
->flags
&= ~STA_FLAG_PRE_AUTH
;
398 /* Fake enough of an EAPOL key message to make WPA happy. */
399 memcpy(&eapol
.eth
.ether_shost
, &sta
->ea
, ETHER_ADDR_LEN
);
400 memcpy(&eapol
.eth
.ether_dhost
, &nas
->ea
, ETHER_ADDR_LEN
);
401 eapol
.eth
.ether_type
= htons(ETHER_TYPE_802_1X
);
402 eapol
.version
= sta
->eapol_version
;
403 eapol
.type
= EAPOL_KEY
;
404 eapol
.length
= EAPOL_WPA_KEY_LEN
;
405 memset(&wpa_key
, 0, sizeof(wpa_key
));
407 if (sta
->mode
& (WPA2_PSK
| WPA2
))
408 wpa_key
.type
= EAPOL_WPA2_KEY
;
411 wpa_key
.type
= EAPOL_WPA_KEY
;
412 wpa_key
.key_info
= htons(WPA_KEY_PAIRWISE
| WPA_KEY_REQ
);
413 /* Put the message pieces together. (They probably were together,
414 * but it's not valid to assume so.
416 memcpy(buffer
, &eapol
, sizeof(eapol
));
417 memcpy(&buffer
[offsetof(eapol_header_t
, body
)], &wpa_key
,
420 /* WPA state should be okay now to start 4-way handshake. */
421 if (process_wpa(wpa
, (eapol_header_t
*)buffer
, sta
)) {
422 cleanup_sta(nas
, sta
, DOT11_RC_8021X_AUTH_FAIL
, 0);
427 /* Send a canned EAPOL packet */
429 eapol_canned(nas_t
*nas
, nas_sta_t
*sta
, unsigned char code
, unsigned char type
)
431 eapol_header_t eapol
;
433 struct iovec frags
[2];
435 memcpy(&eapol
.eth
.ether_dhost
, &sta
->ea
, ETHER_ADDR_LEN
);
436 memcpy(&eapol
.eth
.ether_shost
, &nas
->ea
, ETHER_ADDR_LEN
);
438 if (sta
->flags
& STA_FLAG_PRE_AUTH
)
439 eapol
.eth
.ether_type
= htons(ETHER_TYPE_802_1X_PREAUTH
);
442 eapol
.eth
.ether_type
= htons(ETHER_TYPE_802_1X
);
443 eapol
.version
= sta
->eapol_version
;
444 eapol
.type
= EAP_PACKET
;
445 eapol
.length
= htons(type
? (EAP_HEADER_LEN
+ 1) : EAP_HEADER_LEN
);
448 eap
.id
= sta
->pae
.id
;
449 eap
.length
= eapol
.length
;
452 frags
[0].iov_base
= (caddr_t
) &eapol
;
453 frags
[0].iov_len
= EAPOL_HEADER_LEN
;
454 frags
[1].iov_base
= (caddr_t
) &eap
;
455 frags
[1].iov_len
= ntohs(eapol
.length
);
458 if (sta
->flags
& STA_FLAG_PRE_AUTH
)
459 nas_preauth_send_packet(nas
, frags
, 2);
462 nas_eapol_send_packet(nas
, frags
, 2);
465 #define JAN_1970 0x83aa7e80 /* 2208988800 1970 - 1900 in seconds */
467 /* How to multiply by 4294.967296 quickly (and not quite exactly)
468 * without using floating point or greater than 32-bit integers.
469 * If you want to fix the last 12 microseconds of error, add in
472 #define NTPFRAC(x) (4294*(x) + ((1981*(x))>>11))
474 /* Send a EAPOL-Key packet */
476 eapol_key(nas_t
*nas
, nas_sta_t
*sta
,
477 unsigned char *send_key
, int send_key_len
,
478 unsigned char *recv_key
, int recv_key_len
,
479 unsigned char *key
, int key_len
, int index
, int unicast
)
482 eapol_header_t
*eapol
;
483 eapol_key_header_t
*body
;
487 unsigned short length
;
488 unsigned int replay
[2];
489 unsigned char rc4_seed
[48] = { 0 };
492 /* Allocate packet */
493 packet
.iov_len
= EAPOL_HEADER_LEN
+ EAPOL_KEY_HEADER_LEN
;
495 packet
.iov_len
+= key_len
;
496 if (!(packet
.iov_base
= (caddr_t
) malloc(packet
.iov_len
))) {
501 /* Fill EAPOL header */
502 eapol
= (eapol_header_t
*) packet
.iov_base
;
503 memcpy(&eapol
->eth
.ether_dhost
, &sta
->ea
, ETHER_ADDR_LEN
);
504 memcpy(&eapol
->eth
.ether_shost
, &nas
->ea
, ETHER_ADDR_LEN
);
506 if (sta
->flags
& STA_FLAG_PRE_AUTH
)
507 eapol
->eth
.ether_type
= htons(ETHER_TYPE_802_1X_PREAUTH
);
510 eapol
->eth
.ether_type
= htons(ETHER_TYPE_802_1X
);
511 eapol
->version
= sta
->eapol_version
;
512 eapol
->type
= EAPOL_KEY
;
513 eapol
->length
= htons(packet
.iov_len
- EAPOL_HEADER_LEN
);
515 /* Fill EAPOL-Key header */
516 body
= (eapol_key_header_t
*) eapol
->body
;
517 body
->type
= EAPOL_RC4_KEY
;
519 /* Length field is unaligned */
520 length
= htons(key_len
);
521 memcpy(&body
->length
, &length
, sizeof(body
->length
));
523 /* Replay Counter field is unaligned */
524 gettimeofday(&tv
, &tz
);
526 * keep track timestamp locally in case gettimeofday() does not return
527 * correct usec value, for example, on vx. It is ok to not adjust
528 * tv.tv_sec since tv.tv_usec is not going to overflow anyway.
530 if (tv
.tv_usec
== sta
->rc4keyusec
&& tv
.tv_sec
== sta
->rc4keysec
) {
531 tv
.tv_usec
+= sta
->rc4keycntr
;
535 sta
->rc4keysec
= tv
.tv_sec
;
536 sta
->rc4keyusec
= tv
.tv_usec
;
539 replay
[0] = htonl(tv
.tv_sec
+ JAN_1970
);
540 replay
[1] = htonl(NTPFRAC(tv
.tv_usec
));
541 memcpy(body
->replay
, replay
, sizeof(body
->replay
));
544 nas_rand128(body
->iv
);
549 body
->index
|= EAPOL_KEY_UNICAST
;
553 memcpy(rc4_seed
, body
->iv
, 16);
554 memcpy(&rc4_seed
[16], recv_key
, recv_key_len
);
555 prepare_key(rc4_seed
, 16 + recv_key_len
, &rc4_key
);
556 memcpy(body
->key
, key
, key_len
);
557 rc4(body
->key
, key_len
, &rc4_key
);
560 /* Calculate HMAC-MD5 checksum with null signature */
562 memset(body
->signature
, 0, 16);
563 hmac_md5(&eapol
->version
, packet
.iov_len
- OFFSETOF(eapol_header_t
, version
),
564 send_key
, send_key_len
, body
->signature
);
568 if (sta
->flags
& STA_FLAG_PRE_AUTH
)
569 nas_preauth_send_packet(nas
, &packet
, 1);
572 nas_eapol_send_packet(nas
, &packet
, 1);
573 free(packet
.iov_base
);
577 /* Make a debug message lucid for those who don't know types by number */
579 eapol_msg_type_name(int type_no
)
588 name
= "EAPOL start";
591 name
= "EAPOL logoff";
600 name
= "unexpected type";
608 eapol_dispatch(nas_t
*nas
, eapol_header_t
*eapol
)
610 eapol_dispatch_ex(nas
, eapol
, 0);
615 preauth_dispatch(nas_t
*nas
, eapol_header_t
*eapol
)
617 if (!nas
->disable_preauth
)
618 eapol_dispatch_ex(nas
, eapol
, 1);
623 eapol_dispatch_ex(nas_t
*nas
, eapol_header_t
*eapol
, int preauth
)
628 char eabuf
[ETHER_ADDR_STR_LEN
];
631 /* Validate EAPOL version */
633 dbg(nas
, "Missing EAPOL header");
637 sta
= lookup_sta(nas
, (struct ether_addr
*) eapol
->eth
.ether_shost
,
640 dbg(nas
, "no STA struct available");
643 if (sta
->pae
.state
== HELD
) {
644 dbg(nas
, "nothing done since in HELD state");
647 dbg(nas
, "%s message from %s", eapol_msg_type_name(eapol
->type
),
648 ether_etoa((uchar
*)&sta
->ea
, eabuf
));
649 if (eapol
->version
< sta
->eapol_version
) {
650 dbg(nas
, "EAPOL version %d packet received, current version is %d", eapol
->version
,
657 /* If this is a WPA key pkt then process it accordingly */
658 if ((eapol
->type
== EAPOL_KEY
) &&
659 (CHECK_EAPOL_KEY(eapol
->body
[0]))) {
661 * Expect to do this only for WPA_PSK or for WPA either very
662 * early or after RADIUS acceptance.
664 if ((CHECK_NAS(sta
->mode
)) &&
665 ((sta
->pae
.state
== AUTHENTICATED
) ||
666 (sta
->pae
.state
== INITIALIZE
))) {
667 /* process WPA key pkt */
668 if (process_wpa(nas
->wpa
, eapol
, sta
)) {
669 /* Something wrong in WPA. Lose this sta. */
670 cleanup_sta(nas
, sta
, DOT11_RC_8021X_AUTH_FAIL
, 0);
677 /* break out if STA is only PSK */
678 if (CHECK_PSK(sta
->mode
))
681 sta
->flags
&= ~STA_FLAG_PRE_AUTH
;
684 * instead of passing the state variable saying whether this data is from a pre auth
685 * sta or from a normal store the variable in the sta struct and
686 * would be reset once the message is handled ... state variable makes sense
687 * only for this one message.
690 sta
->flags
|= STA_FLAG_PRE_AUTH
;
692 sta
->eapol_version
= WPA2_EAPOL_VERSION
;
696 /* EAPOL event : Radius support */
697 switch (eapol
->type
) {
700 dbg(nas
, "EAP Packet.Preauth=%d", preauth
);
701 if (ntohs(eapol
->length
) >= (EAP_HEADER_LEN
+ 1)) {
702 eap
= (eap_header_t
*) eapol
->body
;
703 dbg(nas
, "STA State=%d EAP Packet Type=%d Id=%d code=%d",
704 sta
->pae
.state
, eap
->type
, eap
->id
, eap
->code
);
710 if (eap
->id
!= sta
->pae
.id
||
711 eap
->code
!= EAP_RESPONSE
) {
712 dbg(nas
, "bogus EAP packet id %d code %d, expected %d",
713 eap
->id
, eap
->code
, sta
->pae
.id
);
717 if (sta
->pae
.state
== AUTHENTICATING
) {
718 dbg(nas
, "NAS currently authenticating STA. "
719 "Tossing packet id=%d code=%d.",
724 /* Record identity */
725 if (ntohs(eap
->length
) > (EAP_HEADER_LEN
+ 1)) {
726 if (sta
->pae
.radius
.username
.data
)
727 free(sta
->pae
.radius
.username
.data
);
728 sta
->pae
.radius
.username
.length
= ntohs(eap
->length
) -
730 if (!(sta
->pae
.radius
.username
.data
=
731 malloc(sta
->pae
.radius
.username
.length
))) {
735 memcpy(sta
->pae
.radius
.username
.data
, eap
->data
,
736 sta
->pae
.radius
.username
.length
);
738 pae_state(nas
, sta
, AUTHENTICATING
);
744 /* Forward to authentication server */
745 RADIUS_FORWARD(nas
, sta
, eap
);
753 sta
->pae
.id
= 0; /* reset counter */
754 switch (sta
->pae
.state
) {
756 pae_state(nas
, sta
, ABORTING
);
760 pae_state(nas
, sta
, CONNECTING
);
763 sta
->suppl
.state
= sta
->suppl
.retry_state
= WPA_PTKSTART
;
768 switch (sta
->pae
.state
) {
770 dbg(nas
, "Unexpected pae state %d", sta
->pae
.state
);
773 pae_state(nas
, sta
, ABORTING
);
778 pae_state(nas
, sta
, DISCONNECTED
);
779 dbg(nas
, "deauthenticating %s", ether_etoa((uchar
*)&sta
->ea
, eabuf
));
780 nas_deauthorize(nas
, &sta
->ea
);
790 dbg(nas
, "Encapsulated ASF Alert");
794 dbg(nas
, "unknown EAPOL type %d", eapol
->type
);
801 eapol_sup_dispatch(nas_t
*nas
, eapol_header_t
*eapol
)
805 char eabuf
[ETHER_ADDR_STR_LEN
];
809 dbg(nas
, "Missing EAPOL header");
813 sta
= lookup_sta(nas
, (struct ether_addr
*) eapol
->eth
.ether_shost
,
816 dbg(nas
, "No STA struct available");
820 dbg(nas
, "%s message from %s", eapol_msg_type_name(eapol
->type
),
821 ether_etoa((uchar
*)&sta
->ea
, eabuf
));
822 if (eapol
->version
< sta
->eapol_version
) {
823 dbg(nas
, "EAPOL version %d packet received, current version is %d", eapol
->version
,
827 /* If this is a WPA key pkt then process it accordingly */
828 if ((eapol
->type
== EAPOL_KEY
) &&
829 (CHECK_EAPOL_KEY(eapol
->body
[0]))) {
830 /* Expect to do this only for WPA_PSK or for WPA either very
831 * early or after RADIUS acceptance.
833 if ((CHECK_NAS(sta
->mode
)) &&
834 ((sta
->pae
.state
== AUTHENTICATED
) || (sta
->pae
.state
== INITIALIZE
))) {
835 /* process WPA key pkt */
836 if (process_sup_wpa(nas
->wpa
, eapol
, sta
)) {
837 /* Something wrong in WPA. Lose this pae. */
838 cleanup_sta(nas
, sta
, DOT11_RC_8021X_AUTH_FAIL
, 0);
844 err(nas
, "unknown EAPOL type %d", eapol
->type
);
846 #endif /* BCMSUPPL */
849 /* Make a debug message lucid for those who don't know types by number */
851 driver_msg_name(int type
)
856 case WLC_E_ASSOC_IND
:
858 case WLC_E_REASSOC_IND
:
860 case WLC_E_DISASSOC_IND
:
862 case WLC_E_MIC_ERROR
:
871 driver_message_dispatch(nas_t
*nas
, bcm_event_t
*dpkt
)
873 wl_event_msg_t
*event
= &(dpkt
->event
);
874 int type
= ntohl(event
->event_type
);
875 uint8
*addr
= (uint8
*)&(event
->addr
);
878 char eabuf
[ETHER_ADDR_STR_LEN
];
881 /* !!!THESE ARE THE MESSAGES WE CARE!!! */
882 dbg(nas
, "received event of type : %d\n", type
);
885 /* WLC_E_LINK evnet on WDS is use for trigger nas_start */
886 if (nas
->flags
& NAS_FLAG_WDS
)
888 /* authenticator is not interested in LINK event */
889 if (nas
->flags
& NAS_FLAG_AUTHENTICATOR
)
891 /* and the supplicant is only interested in link up */
892 if (!(ntohs(event
->flags
) & WLC_EVENT_MSG_LINK
)) {
895 case WLC_E_ASSOC_IND
:
896 case WLC_E_REASSOC_IND
:
897 case WLC_E_DISASSOC_IND
:
898 case WLC_E_MIC_ERROR
:
901 /* quietly discard unwanted events */
907 dbg(nas
, "driver %s message received for %s", driver_msg_name(type
),
908 ether_etoa(addr
, eabuf
));
910 /* Look for the STA struct, but don't create one if the goal is
913 sta
= lookup_sta(nas
, (struct ether_addr
*)addr
,
914 type
== WLC_E_DISASSOC_IND
? SEARCH_ONLY
: SEARCH_ENTER
);
919 case WLC_E_ASSOC_IND
:
920 case WLC_E_REASSOC_IND
:
921 if (!(CHECK_NAS(nas
->mode
))) {
922 dbg(nas
, "Unexpected driver %s message in mode %d", driver_msg_name(type
),
926 if (wpa_driver_assoc_msg(nas
->wpa
, dpkt
, sta
) == 0)
929 /* clean-up stuff if there was a problem. */
931 cleanup_sta(nas
, sta
, 0, 1);
935 case WLC_E_DISASSOC_IND
:
936 if (wpa_driver_disassoc_msg(nas
->wpa
, dpkt
, sta
) == 0)
939 /* clean-up stuff if there was a problem. */
941 cleanup_sta(nas
, sta
, 0, 1);
945 case WLC_E_MIC_ERROR
:
946 if ((ntohs(event
->flags
) & WLC_EVENT_MSG_GROUP
) &&
947 (nas
->flags
& NAS_FLAG_AUTHENTICATOR
)) {
948 dbg(nas
, "GTK MIC error notification received by AP");
954 If an error is attributed to a STA we don't know about,
957 Otherwise, call wpa_mic_error for processing
962 dbg(nas
, "PTK MIC error notification received by AP");
963 wpa_mic_error(nas
->wpa
, sta
, TRUE
);
967 "PTK MIC error notification received by AP but not from a known STA");
973 dbg(nas
, "Tossing unexpected event #%u", type
);
980 nas_watchdog(bcm_timer_id td
, nas_t
*nas
)
985 char eabuf
[ETHER_ADDR_STR_LEN
];
987 for (i
= 0; i
< MAX_SUPPLICANTS
; i
++) {
988 for (sta
= nas
->sta_hashed
[i
]; sta
; sta
= sta
->next
) {
990 if (nas
->auth_blockout_time
) {
991 if (sta
->pae
.flags
& PAE_FLAG_RADIUS_ACCESS_REJECT
)
992 dbg(nas
, "blocking %s, time remaining = %d",
993 ether_etoa((uchar
*)&sta
->ea
, eabuf
), sta
->quiet_while
);
996 /* check for time out */
997 switch (sta
->pae
.state
) {
1005 /* send Identity Request */
1006 dbg(nas
, "ID req to %s\n", ether_etoa((uchar
*)&sta
->ea
, eabuf
));
1007 send_identity_req(nas
, sta
);
1010 if (sta
->quiet_while
&& --sta
->quiet_while
== 0)
1011 pae_state(nas
, sta
, CONNECTING
);
1014 if (sta
->tx_when
&& --sta
->tx_when
== 0) {
1015 if (sta
->rxauths
> STA_REAUTH_MAX
)
1016 pae_state(nas
, sta
, DISCONNECTED
);
1018 pae_state(nas
, sta
, CONNECTING
);
1021 case AUTHENTICATING
:
1022 if (sta
->auth_while
&& --sta
->auth_while
== 0) {
1023 pae_state(nas
, sta
, ABORTING
);
1024 pae_state(nas
, sta
, CONNECTING
);
1035 nas_start_watchdog(nas_t
*nas
)
1039 if (nas
->watchdog_td
)
1040 TIMER_DELETE(nas
->watchdog_td
);
1042 ts
= wpa_set_itimer(nas
->timer
, &nas
->watchdog_td
,
1043 (bcm_timer_cb
)nas_watchdog
,
1045 if (ts
!= ITIMER_OK
)
1046 dbg(nas
, "Session timeout timer set failed, code %d", ts
);
1050 nas_start(nas_t
*nas
)
1054 /* reset all STAs */
1055 bzero((void *)nas
->sta
, sizeof(nas
->sta
));
1056 bzero((void *)nas
->sta_hashed
, sizeof(nas
->sta_hashed
));
1057 nas
->MIC_failures
= 0;
1058 nas
->MIC_countermeasures
= 0;
1059 nas
->prev_MIC_error
= 0;
1061 /* start session count down timer */
1062 if (CHECK_RADIUS(nas
->mode
))
1063 nas_start_watchdog(nas
);
1065 /* initiate/request pairwise key exchange */
1066 if (!(nas
->flags
& NAS_FLAG_WDS
))
1069 sta
= lookup_sta(nas
, (struct ether_addr
*)nas
->remote
,
1073 char eabuf
[ETHER_ADDR_STR_LEN
];
1075 dbg(nas
, "sta %s not available", ether_etoa(nas
->remote
, eabuf
));
1079 /* Assume the peer use the same cipher and akm */
1080 if (CHECK_PSK(nas
->mode
)) {
1081 sta
->suppl
.pmk_len
= nas
->wpa
->pmk_len
;
1082 bcopy(nas
->wpa
->pmk
, sta
->suppl
.pmk
, nas
->wpa
->pmk_len
);
1085 * There is no beacon/proberesp/assocreq across WDS, therefore
1086 * we have no way to know what cipher and akm the peer is configured
1087 * for. But assuming the peer uses the same configuration seems
1088 * reasonable. No WEP when doing WPA over WDS.
1090 wpa_set_suppl(nas
->wpa
, sta
, nas
->mode
, nas
->wsec
, CRYPTO_ALGO_OFF
);
1093 if (nas
->flags
& NAS_FLAG_SUPPLICANT
)
1094 wpa_request(nas
->wpa
, sta
);
1096 if (nas
->flags
& NAS_FLAG_AUTHENTICATOR
)
1097 wpa_start(nas
->wpa
, sta
);
1101 nas_handle_error(nas_t
*nas
, int error
)
1103 /* Handle the Error cases one by one */
1104 err(nas
, "NAS encountered a non recoverable Error, so resetting the board\n");