source: src/router/rt2860apd/ieee802_1x.c @ 17793

Last change on this file since 17793 was 17793, checked in by chris, 20 months ago

qos rewrite pppd/radius needs testing

File size: 30.7 KB
Line 
1/*
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation. See README and COPYING for
6 * more details.
7
8        Module Name:
9        ieee802_1x.c
10
11        Revision History:
12        Who             When              What
13        --------        ----------        ----------------------------------------------
14        Jan, Lee        Dec --2003        modified
15
16*/
17
18#include <stdlib.h>
19#include <stdio.h>
20#include <unistd.h>
21#include <netinet/in.h>
22#include <string.h>
23#include <sys/ioctl.h>
24#include <signal.h>
25#include <assert.h>
26#include <time.h>
27#include <sys/time.h>
28#include <sys/socket.h>
29
30#include <linux/if.h>                   /* for IFNAMSIZ and co... */
31#include <linux/wireless.h>
32
33#include "rt2860apd.h"
34#include "ieee802_1x.h"
35#include "radius.h"
36#include "radius_client.h"
37#include "eapol_sm.h"
38#include "md5.h"
39#include "eloop.h"
40#include "sta_info.h"
41
42static void ieee802_1x_send(rtapd *rtapd, struct sta_info *sta, u8 type, u8 *data, size_t datalen)
43{
44        char *buf;
45        struct ieee8023_hdr *hdr3;
46        struct ieee802_1x_hdr *xhdr;
47        size_t len;
48        u8 *pos;
49                   
50        len = sizeof(*hdr3) + 2+ sizeof(*xhdr) +datalen;
51        buf = (char *) malloc(len);
52        if (buf == NULL)
53        {
54                DBGPRINT(RT_DEBUG_ERROR,"malloc() failed for ieee802_1x_send(len=%d)\n", len);
55                return;
56        }
57        DBGPRINT(RT_DEBUG_TRACE,"Send to Sta(%s%d) with Identifier %d\n", rtapd->prefix_wlan_name, sta->ApIdx,*(data+1));
58        memset(buf, 0, len);
59        hdr3 = (struct ieee8023_hdr *) buf;
60        memcpy(hdr3->dAddr, sta->addr, ETH_ALEN);
61        memcpy(hdr3->sAddr, rtapd->own_addr[sta->ApIdx], ETH_ALEN);
62
63        if (sta->ethertype == ETH_P_PRE_AUTH)
64                (hdr3->eth_type) = htons(ETH_P_PRE_AUTH);
65        else
66                (hdr3->eth_type) = htons(ETH_P_PAE);
67
68        pos = (u8 *) (hdr3 + 1);
69        xhdr = (struct ieee802_1x_hdr *) pos;
70        if (sta->ethertype == ETH_P_PRE_AUTH)
71                xhdr->version = EAPOL_VERSION_2;
72        else
73                xhdr->version = EAPOL_VERSION;
74        xhdr->type = type;
75        xhdr->length = htons(datalen);
76
77        if (datalen > 0 && data != NULL)
78                memcpy(pos + LENGTH_8021X_HDR, data, datalen);
79
80        //If (ethertype==ETH_P_PRE_AUTH), this means the packet is to or from ehternet socket(WPA2, pre-auth)
81        if (sta->ethertype == ETH_P_PRE_AUTH)
82        {
83                if (send(sta->SockNum/*rtapd->eth_sock*/, buf, len, 0) < 0)
84                        perror("send[WPA2 pre-auth]");
85                DBGPRINT(RT_DEBUG_INFO,"ieee802_1x_send::WPA2, pre-auth, len=%d\n", len);
86        }
87        else
88        {
89        if (RT_ioctl(rtapd->ioctl_sock,
90                                         RT_PRIV_IOCTL, buf, len,
91                                         rtapd->prefix_wlan_name, sta->ApIdx,
92                                         RT_OID_802_DOT1X_RADIUS_DATA))
93        DBGPRINT(RT_DEBUG_ERROR,"ioctl failed for ieee802_1x_send(len=%d)\n", len);
94        }
95
96        free(buf);
97}
98
99void ieee802_1x_set_sta_authorized(rtapd *rtapd, struct sta_info *sta, int authorized)
100{
101        switch(authorized)
102        {
103                case 0:
104                        DBGPRINT(RT_DEBUG_TRACE,"IEEE802_1X_Set_Sta_Authorized FAILED \n");
105//                        Ap_free_sta(rtapd, sta);
106                        break;
107
108                case 1:
109                        DBGPRINT(RT_DEBUG_TRACE,"IEEE802_1X_Set_Sta_Authorized SUCCESSED  \n");                   
110                       
111                        // This connection completed without transmitting EAPoL-Key
112                        // Notify driver to set-up pairwise key based on its shared key
113                        if( sta->eapol_sm->authSuccess && sta->eapol_key_sign_len == 0 && sta->eapol_key_crypt_len == 0 )
114                        {
115                                UCHAR   MacAddr[MAC_ADDR_LEN];
116                               
117                                memcpy(MacAddr, sta->addr, MAC_ADDR_LEN);
118                                if (RT_ioctl(rtapd->ioctl_sock,
119                                                         RT_PRIV_IOCTL,
120                                                         (char *)&MacAddr, sizeof(MacAddr),
121                                                         rtapd->prefix_wlan_name, sta->ApIdx,
122                                                         RT_OID_802_DOT1X_STATIC_WEP_COPY))
123                                {                                 
124                        DBGPRINT(RT_DEBUG_ERROR,"Failed to RT_OID_802_DOT1X_STATIC_WEP_COPY\n");
125                        return;
126                                }   
127                }
128                        break;   
129        }
130}
131
132void ieee802_1x_request_identity(rtapd *rtapd, struct sta_info *sta, u8 id)
133{
134        u8 *buf;
135        struct eap_hdr *eap;
136        int tlen;
137        u8 *pos;
138
139        ieee802_1x_new_auth_session(rtapd, sta);
140
141        tlen = sizeof(*eap) + 1 ;
142
143        buf = (u8 *) malloc(tlen);
144        if (buf == NULL)
145        {
146                DBGPRINT(RT_DEBUG_ERROR, "Could not allocate memory for identity request\n");
147                return;
148        }
149
150        memset(buf, 0, tlen);
151
152        eap = (struct eap_hdr *) buf;
153        eap->code = EAP_CODE_REQUEST;
154        eap->identifier = id;
155        eap->length = htons(tlen);
156        pos = (u8 *) (eap + 1);
157        *pos++ = EAP_TYPE_IDENTITY;
158
159        DBGPRINT(RT_DEBUG_INFO, "IEEE802_1X_Request_Identity %d bytes: \n",tlen);
160        ieee802_1x_send(rtapd, sta, IEEE802_1X_TYPE_EAP_PACKET, buf, tlen);
161        free(buf);
162}
163
164void ieee802_1x_tx_canned_eap(rtapd *rtapd, struct sta_info *sta, u8 id, int success)
165{
166        struct eap_hdr eap;
167
168        memset(&eap, 0, sizeof(eap));
169
170        eap.code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE;
171        eap.identifier = id;
172        eap.length = htons(sizeof(eap));
173        DBGPRINT(RT_DEBUG_TRACE,"ieee802_1x_tx_canned_eap : Send to Sta with Identifier %d\n",id);
174
175        ieee802_1x_send(rtapd, sta, IEEE802_1X_TYPE_EAP_PACKET, (u8 *) &eap, sizeof(eap));
176}
177
178void ieee802_1x_tx_req(rtapd *rtapd, struct sta_info *sta, u8 id)
179{
180        struct eap_hdr *eap;
181
182        if (sta->last_eap_radius == NULL)
183        {
184                DBGPRINT(RT_DEBUG_WARN, "TxReq called for station " MACSTR ", but there "
185                           "is no EAP request from the authentication server\n", MAC2STR(sta->addr));
186                return;
187        }
188
189        eap = (struct eap_hdr *) sta->last_eap_radius;
190        if (eap->identifier != id)
191        {
192                DBGPRINT(RT_DEBUG_WARN,"IEEE 802.1X: TxReq(%d) - changing id from %d\n", id, eap->identifier);
193                eap->identifier = id;
194        }
195
196        ieee802_1x_send(rtapd, sta, IEEE802_1X_TYPE_EAP_PACKET, sta->last_eap_radius, sta->last_eap_radius_len);
197}
198
199static void ieee802_1x_tx_key_one(rtapd *hapd, struct sta_info *sta,
200                                  int index, int broadcast,
201                                  u8 *key_data, size_t key_len)
202{
203        u8 *buf, *ekey;
204        struct ieee802_1x_hdr *hdr;
205        struct ieee802_1x_eapol_key *key;
206        struct timeval now;
207        size_t len, ekey_len;
208        u32 ntp_hi, ntp_lo, sec, usec;
209
210        len = sizeof(*key) + key_len;
211        buf = malloc(sizeof(*hdr) + len);
212        if (buf == NULL)
213                return;
214
215        memset(buf, 0, sizeof(*hdr) + len);
216        hdr = (struct ieee802_1x_hdr *) buf;
217        key = (struct ieee802_1x_eapol_key *) (hdr + 1);
218        key->type = EAPOL_KEY_TYPE_RC4;
219        key->key_length = htons(key_len);
220
221        /* Set the NTP timestamp as the replay counter */
222        gettimeofday(&now, NULL);
223        sec = now.tv_sec;
224        usec = now.tv_usec;
225
226#define JAN_1970 0x83aa7e80UL /* seconds from 1900 to 1970 */
227        ntp_hi = htonl(sec + JAN_1970);
228        /* approximation of 2^32/1000000 * usec */
229        ntp_lo = htonl(4295 * usec - (usec >> 5) - (usec >> 9));
230
231        memcpy(&key->replay_counter[0], &ntp_hi, sizeof(u32));
232        memcpy(&key->replay_counter[4], &ntp_lo, sizeof(u32));
233        if (hostapd_get_rand(key->key_iv, sizeof(key->key_iv)))
234        {
235                DBGPRINT(RT_DEBUG_ERROR, "Could not get random numbers\n");
236                free(buf);
237                return;
238        }
239
240        key->key_index = index | (broadcast ? 0 : BIT(7));
241//      if (hapd->conf->eapol_key_index_workaround) {
242                /* According to some information, WinXP Supplicant seems to
243                 * interrept bit7 as an indication whether the key is to be
244                 * activated, so make it possible to enable workaround that
245                 * sets this bit for all keys. */
246//              key->key_index |= BIT(7);
247//      }
248        DBGPRINT(RT_DEBUG_TRACE, "key_index= %d key_length= %d \n",index, key_len);
249
250        /* Key is encrypted using "Key-IV + sta->eapol_key_crypt" as the
251         * RC4-key */
252        memcpy((u8 *) (key + 1), key_data, key_len);
253        ekey_len = sizeof(key->key_iv) + sta->eapol_key_crypt_len;
254        ekey = malloc(ekey_len);
255        if (ekey == NULL)
256        {
257                DBGPRINT(RT_DEBUG_TRACE,"Could not encrypt key\n");
258                free(buf);
259                return;
260        }
261        memcpy(ekey, key->key_iv, sizeof(key->key_iv));
262        memcpy(ekey + sizeof(key->key_iv), sta->eapol_key_crypt, sta->eapol_key_crypt_len);
263        rc4((u8 *) (key + 1), key_len, ekey, ekey_len);
264        free(ekey);
265
266        /* This header is needed here for HMAC-MD5, but it will be regenerated in ieee802_1x_send() */
267        hdr->version = EAPOL_VERSION;
268        hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;
269        hdr->length = htons(len);
270        hmac_md5(sta->eapol_key_sign, sta->eapol_key_sign_len, buf, sizeof(*hdr) + len, key->key_signature);
271
272        ieee802_1x_send(hapd, sta, IEEE802_1X_TYPE_EAPOL_KEY, (u8 *) key, len);
273        free(buf);
274}
275
276void ieee802_1x_tx_key(rtapd *rtapd, struct sta_info *sta, u8 id)
277{
278        NDIS_802_11_KEY         WepKey, *pWepKey;
279       char individual_wep_key[WEP8021X_KEY_LEN];
280       
281        if (!sta->eapol_key_sign || !sta->eapol_key_crypt)
282                return;
283
284        memset(&WepKey, 0, sizeof(NDIS_802_11_KEY));
285        pWepKey = &WepKey;
286
287        // prepare EAPoL-key for broadcast key and send to STA
288        ieee802_1x_tx_key_one(rtapd, sta, rtapd->conf->DefaultKeyID[sta->ApIdx], 1, (u8*)rtapd->conf->IEEE8021X_ikey[sta->ApIdx], rtapd->conf->individual_wep_key_len[sta->ApIdx]);
289       
290        // use IOCTL cmd to add WEP key
291        WepKey.KeyIndex =  0x80000000 | (rtapd->conf->DefaultKeyID[sta->ApIdx]);
292        WepKey.KeyLength = rtapd->conf->individual_wep_key_len[sta->ApIdx];
293        memcpy(WepKey.KeyMaterial, rtapd->conf->IEEE8021X_ikey[sta->ApIdx], rtapd->conf->individual_wep_key_len[sta->ApIdx]);
294        memcpy(WepKey.addr, sta->addr, 6);
295
296        // WPA2(pre-auth)
297        if (sta->ethertype== ETH_P_PRE_AUTH)
298        {
299                if (RT_ioctl(rtapd->ioctl_sock,
300                                         RT_PRIV_IOCTL,
301                                         (char *)&WepKey,
302                                         sizeof(NDIS_802_11_KEY),
303                                         rtapd->prefix_wlan_name, 0,
304                                         RT_OID_802_DOT1X_PMKID_CACHE))
305                {
306                        DBGPRINT(RT_DEBUG_ERROR, "ieee802_1x_tx_key:RT_OID_802_DOT1X_PMKID_CACHE\n");
307                        return;
308                }
309        }
310        else
311        {
312                if (RT_ioctl(rtapd->ioctl_sock,
313                                         RT_PRIV_IOCTL,
314                                         (char *)&WepKey,
315                                         sizeof(NDIS_802_11_KEY),
316                                         rtapd->prefix_wlan_name,
317                                         sta->ApIdx,
318                                         RT_OID_802_DOT1X_WPA_KEY))
319                {
320                        DBGPRINT(RT_DEBUG_ERROR,"ieee802_1x_tx_key:RT_OID_802_DOT1X_WPA_KEY\n");
321                        return;
322                }
323        }
324       
325    // Generate random unicast key and send to STA
326    hostapd_get_rand((u8*)individual_wep_key, rtapd->conf->individual_wep_key_len[sta->ApIdx]);
327    ieee802_1x_tx_key_one(rtapd, sta, rtapd->conf->individual_wep_key_idx[sta->ApIdx], 0, (u8*)individual_wep_key, rtapd->conf->individual_wep_key_len[sta->ApIdx]);
328
329        // use IOCTL cmd to add WEP key
330        WepKey.KeyIndex =  rtapd->conf->individual_wep_key_idx[sta->ApIdx];
331        WepKey.KeyLength = rtapd->conf->individual_wep_key_len[sta->ApIdx];
332        memcpy(WepKey.KeyMaterial, individual_wep_key, rtapd->conf->individual_wep_key_len[sta->ApIdx]);
333        memcpy(WepKey.addr, sta->addr, 6);
334
335        // WPA2(pre-auth)
336        if (sta->ethertype == ETH_P_PRE_AUTH)
337        {
338                if (RT_ioctl(rtapd->ioctl_sock,
339                                         RT_PRIV_IOCTL,
340                                         (char *)&WepKey,
341                                         sizeof(NDIS_802_11_KEY),
342                                         rtapd->prefix_wlan_name, 0,
343                                         RT_OID_802_DOT1X_PMKID_CACHE))
344                {
345                        DBGPRINT(RT_DEBUG_ERROR,"ieee802_1x_tx_key:RT_OID_802_DOT1X_PMKID_CACHE\n");
346                        return;
347                }
348        }
349        else
350        {
351                if (RT_ioctl(rtapd->ioctl_sock,
352                                         RT_PRIV_IOCTL,
353                                         (char *)&WepKey,
354                                         sizeof(NDIS_802_11_KEY),
355                                         rtapd->prefix_wlan_name,
356                                         sta->ApIdx,
357                                         RT_OID_802_DOT1X_WPA_KEY))
358                {
359                        DBGPRINT(RT_DEBUG_ERROR,"ieee802_1x_tx_key:RT_OID_802_DOT1X_WPA_KEY\n");
360                        return;
361                }
362        }
363}
364
365static void ieee802_1x_encapsulate_radius(rtapd *rtapd, struct sta_info *sta, u8 *eap, size_t len)
366{
367        struct radius_msg *msg;
368        u8 buf[128];
369        int     res;
370
371        sta->radius_identifier = Radius_client_get_id(rtapd);
372        msg = Radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, sta->radius_identifier);
373        if (msg == NULL)
374        {
375                DBGPRINT(RT_DEBUG_ERROR, "Could not create net RADIUS packet\n");
376                return;
377        }
378
379        Radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(sta));
380
381        if (sta->identity && !Radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, sta->identity, sta->identity_len))
382        {
383                DBGPRINT(RT_DEBUG_ERROR,"Could not add User-Name\n");
384                goto fail;
385        }
386           // apd->conf->own_ip_addr is filled according to configuration file
387        if (!Radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, (u8 *) &rtapd->conf->own_ip_addr, 4))
388        {
389                DBGPRINT(RT_DEBUG_ERROR,"Could not add NAS-IP-Address\n");
390                goto fail;
391        }
392
393        if ((rtapd->conf->nasId_len[sta->ApIdx] > 0) &&
394            !Radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
395                                 rtapd->conf->nasId[sta->ApIdx],
396                                 rtapd->conf->nasId_len[sta->ApIdx]))
397        {
398                DBGPRINT(RT_DEBUG_ERROR, "Could not add NAS-Identifier\n");
399                goto fail;
400        }
401
402        if (!Radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid))
403        {
404                DBGPRINT(RT_DEBUG_ERROR,"Could not add NAS-Port\n");
405                goto fail;
406        }
407       
408        snprintf((char *)&buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, MAC2STR(rtapd->own_addr[sta->ApIdx]));
409        if (!Radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, buf, strlen((char *)&buf)))
410        {
411                DBGPRINT(RT_DEBUG_ERROR,"Could not add Called-Station-Id\n");
412                goto fail;
413        }
414
415        snprintf((char *)&buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, MAC2STR(sta->addr));
416        if (!Radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, buf, strlen((char *)&buf)))
417        {
418                DBGPRINT(RT_DEBUG_ERROR,"Could not add Calling-Station-Id\n");
419                goto fail;
420        }
421
422        /* TODO: should probably check MTU from driver config; 2304 is max for
423         * IEEE 802.11, but use 1400 to avoid problems with too large packets
424         */
425        if (!Radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400))
426        {
427                DBGPRINT(RT_DEBUG_ERROR,"Could not add Framed-MTU\n");
428                goto fail;
429        }
430
431        if (!Radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, RADIUS_NAS_PORT_TYPE_IEEE_802_11))
432        {
433                DBGPRINT(RT_DEBUG_ERROR,"Could not add NAS-Port-Type\n");
434                goto fail;
435        }
436/*
437        snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b");
438        if (!Radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, buf, strlen(buf)))
439        {
440                DBGPRINT(RT_DEBUG_ERROR,"Could not add Connect-Info\n");
441                goto fail;
442        }
443*/
444        if (eap && !Radius_msg_add_eap(msg, eap, len))
445        {
446                DBGPRINT(RT_DEBUG_ERROR,"Could not add EAP-Message\n");
447                goto fail;
448        }
449
450        /* State attribute must be copied if and only if this packet is
451         * Access-Request reply to the previous Access-Challenge */
452        if (sta->last_recv_radius && sta->last_recv_radius->hdr->code == RADIUS_CODE_ACCESS_CHALLENGE)
453        {
454                int res = Radius_msg_copy_attr(msg, sta->last_recv_radius, RADIUS_ATTR_STATE);
455                if (res < 0)
456                {
457                        DBGPRINT(RT_DEBUG_ERROR,"Could not copy State attribute from previous Access-Challenge\n");
458                        goto fail;
459                }
460        }
461
462        res = Radius_client_send(rtapd, msg, RADIUS_AUTH, sta->ApIdx);
463        DBGPRINT(RT_DEBUG_TRACE, "Finish Radius_client_send..(%d)\n", res);
464
465        return;
466
467fail:
468        Radius_msg_free(msg);
469        free(msg);
470}
471
472static void handle_eap_response(struct sta_info *sta, struct eap_hdr *eap, u8 *data, size_t len)
473{
474        u8 type;
475
476        assert(sta->eapol_sm != NULL);
477
478        if (eap->identifier != sta->eapol_sm->currentId)
479        {
480                DBGPRINT(RT_DEBUG_INFO,"EAP Identifier of the Response-Identity from " MACSTR
481                           " does not match (was %d, expected %d)\n",
482                           MAC2STR(sta->addr), eap->identifier,
483                           sta->eapol_sm->currentId);
484                // didn't check identifier..  reasonable ?
485                return;
486        }
487
488        if (len < 1)
489        {
490                DBGPRINT(RT_DEBUG_WARN,"too short response data\n");
491                return;
492        }
493
494        if (sta->last_eap_supp != NULL)
495                free(sta->last_eap_supp);
496               sta->last_eap_supp_len = sizeof(*eap) + len;
497               sta->last_eap_supp = (u8 *) malloc(sta->last_eap_supp_len);
498        if (sta->last_eap_supp == NULL)
499        {
500                DBGPRINT(RT_DEBUG_ERROR,"Could not alloc memory for last EAP Response\n");
501                return;
502        }
503
504        memcpy(sta->last_eap_supp, eap, sizeof(*eap));
505        memcpy(sta->last_eap_supp + sizeof(*eap), data, len);
506
507        type = data[0];
508        data++;
509        len--;
510
511        /* TODO: IEEE 802.1aa/D4: should use auth_pae.initialEAPMsg to check
512         * which EAP packet is accepted as response; currently, hostapd only
513         * supports EAP Response-Identity, so this can be hardcoded */
514        if (type == EAP_TYPE_IDENTITY)
515        {
516                char *buf, *pos;
517                int i;
518
519                buf = malloc(4 * len + 1);
520                if (buf)
521                {
522                        pos = buf;
523                        for (i = 0; i < len; i++)
524                        {
525                                if (data[i] >= 32 && data[i] < 127)
526                                        *pos++ = data[i];
527                                else
528                                {
529                                        snprintf(pos, 5, "{%02x}", data[i]);
530                                        pos += 4;
531                                }
532                        }
533                        *pos = '\0';
534                        free(buf);
535                }
536
537                sta->eapol_sm->auth_pae.rxInitialRsp = TRUE;
538
539                /* Save station identity for future RADIUS packets */
540                if (sta->identity)
541                        free(sta->identity);
542                sta->identity = (u8 *) malloc(len);
543                if (sta->identity)
544                {
545                        memcpy(sta->identity, data, len);
546                        sta->identity_len = len;
547                }
548        }
549        else
550        {
551                if (type != EAP_TYPE_NAK)
552                        sta->eapol_sm->be_auth.backendNonNakResponsesFromSupplicant++;
553                sta->eapol_sm->be_auth.rxResp = TRUE;
554        }
555}
556
557/* Process incoming EAP packet from Supplicant */
558static void handle_eap(struct sta_info *sta, u8 *buf, size_t len)
559{
560        struct eap_hdr *eap;
561        u16 eap_len;
562
563        if (len < sizeof(*eap))
564        {
565                DBGPRINT(RT_DEBUG_ERROR," too short EAP packet\n");
566                return;
567        }
568
569        eap = (struct eap_hdr *) buf;
570
571        eap_len = ntohs(eap->length);
572        DBGPRINT(RT_DEBUG_INFO," Receive EAP: code=%d identifier=%d length=%d from Supplicant ra%d\n",
573                          eap->code, eap->identifier, eap_len,sta->ApIdx);
574        if (eap_len < sizeof(*eap))
575        {
576                DBGPRINT(RT_DEBUG_ERROR,"Invalid EAP length\n");
577                return;
578        }
579        else if (eap_len > len)
580        {
581                DBGPRINT(RT_DEBUG_ERROR,"Too short frame to contain this EAP packet\n");
582                return;
583        }
584        else if (eap_len < len)
585        {
586                DBGPRINT(RT_DEBUG_WARN,"Ignoring %d extra bytes after EAP packet\n", len - eap_len);
587        }
588
589        eap_len -= LENGTH_8021X_HDR;
590
591        switch (eap->code)
592        {
593                case EAP_CODE_REQUEST:
594                        return;
595
596                case EAP_CODE_RESPONSE:
597                        handle_eap_response( sta, eap, (u8 *) (eap + 1), eap_len);
598                        break;
599
600                case EAP_CODE_SUCCESS:
601                        return;
602
603                case EAP_CODE_FAILURE:
604                        return;
605
606                default:
607                        return;
608        }
609}
610
611/* called from handle_read(). Process the EAPOL frames from the Supplicant */
612void ieee802_1x_receive(
613                rtapd *rtapd,
614                u8 *sa,
615                u8 *apidx,
616                u8 *buf,
617                size_t len,
618                u16 ethertype,
619                int     SockNum)
620{
621        struct sta_info *sta;
622        struct ieee802_1x_hdr *hdr;
623        char SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
624        UCHAR   RalinkIe[9] = {221, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00};
625        u16 datalen;
626        int bStop = 0;
627
628        DBGPRINT(RT_DEBUG_TRACE,"IEEE802_1X_RECEIVE : from Supplicant\n");
629       
630        if (len == sizeof(RalinkIe) && RTMPCompareMemory(buf, RalinkIe, sizeof(RalinkIe)) == 0)
631                bStop = 1;
632       
633        sta = Ap_get_sta(rtapd, sa, apidx, ethertype, bStop, SockNum);
634        if (!sta)
635        {
636                return;
637        }
638        if (RTMPCompareMemory(buf, SNAP_802_1H, 6) == 0)
639                buf += LENGTH_802_1_H;
640        hdr = (struct ieee802_1x_hdr *) buf;
641        datalen = ntohs(hdr->length);
642       
643        if (len - sizeof(*hdr) < datalen)
644        {
645                DBGPRINT(RT_DEBUG_ERROR,"Frame too short for this IEEE 802.1X packet\n");
646                return;
647        }
648
649        if (len - sizeof(*hdr) > datalen)
650        {
651        }
652
653        if (!sta->eapol_sm)
654        {
655                sta->eapol_sm = eapol_sm_alloc(rtapd, sta);
656                if (!sta->eapol_sm)
657                        return;
658        }
659
660        /* Check protocol type */
661        if ((ethertype != ETH_P_PAE) && (ethertype != ETH_P_PRE_AUTH))
662        {
663                DBGPRINT(RT_DEBUG_ERROR, "Unsupported Protocol Type (%d)\n", ethertype);
664                return;
665        }
666
667        /* Check EAPoL Protocol Version */
668        if ((hdr->version != EAPOL_VERSION) && (hdr->version != EAPOL_VERSION_2))
669        {
670                DBGPRINT(RT_DEBUG_ERROR, "Unsupported EAPoL Protocol Version (%d)\n", hdr->version);
671                return;
672        }
673
674        switch (hdr->type)
675        {
676                case IEEE802_1X_TYPE_EAP_PACKET:
677                        DBGPRINT(RT_DEBUG_TRACE,"Handle EAP_PACKET from %s%d\n", rtapd->prefix_wlan_name, sta->ApIdx);
678                        handle_eap(sta, (buf + LENGTH_8021X_HDR), datalen);
679                        break;
680
681                case IEEE802_1X_TYPE_EAPOL_START:
682                        DBGPRINT(RT_DEBUG_TRACE,"Handle EAPOL_START from %s%d\n", rtapd->prefix_wlan_name, sta->ApIdx);
683                        sta->eapol_sm->auth_pae.eapStart = TRUE;
684                        eapol_sm_step(sta->eapol_sm);
685                        break;
686
687                case IEEE802_1X_TYPE_EAPOL_LOGOFF:
688                        sta->eapol_sm->auth_pae.eapLogoff = TRUE;
689                        eapol_sm_step(sta->eapol_sm);
690                        break;
691
692                case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT:
693                        /* TODO: */
694                        DBGPRINT(RT_DEBUG_TRACE,"Handle EAPOL_ALERT from %s%d\n", rtapd->prefix_wlan_name, sta->ApIdx);
695                        break;
696
697                default:
698                        DBGPRINT(RT_DEBUG_TRACE,"Handle Unknown EAP message(Type:%d) from %s%d\n",hdr->type, rtapd->prefix_wlan_name, sta->ApIdx);
699                        break;
700        }
701
702        eapol_sm_step(sta->eapol_sm);
703}
704
705void ieee802_1x_new_station(rtapd *rtapd, struct sta_info *sta)
706{
707        if (sta->eapol_sm)
708        {
709                sta->eapol_sm->portEnabled = TRUE;
710                eapol_sm_step(sta->eapol_sm);
711                return;
712        }
713
714        sta->eapol_sm = eapol_sm_alloc(rtapd, sta);
715        if (sta->eapol_sm)
716                sta->eapol_sm->portEnabled = TRUE;
717}
718
719void ieee802_1x_free_station(struct sta_info *sta)
720{
721        if (sta->last_recv_radius)
722        {
723                Radius_msg_free(sta->last_recv_radius);
724                free(sta->last_recv_radius);
725                sta->last_recv_radius = NULL;
726        }
727
728        free(sta->last_eap_supp);
729        sta->last_eap_supp = NULL;
730
731        free(sta->last_eap_radius);
732        sta->last_eap_radius = NULL;
733
734        free(sta->identity);
735        sta->identity = NULL;
736
737        free(sta->eapol_key_sign);
738        sta->eapol_key_sign = NULL;
739
740        free(sta->eapol_key_crypt);
741        sta->eapol_key_crypt = NULL;
742
743        eapol_sm_free(sta->eapol_sm);
744        sta->eapol_sm = NULL;
745}
746
747static void ieee802_1x_decapsulate_radius(struct sta_info *sta)
748{
749        u8 *eap;
750        size_t len;
751        struct eap_hdr *hdr;
752        int eap_type = -1;
753        struct radius_msg *msg;
754
755        if (sta->last_recv_radius == NULL)
756                return;
757
758        msg = sta->last_recv_radius;
759        eap = Radius_msg_get_eap(msg, &len);
760        if (eap == NULL)
761        {
762                /* draft-aboba-radius-rfc2869bis-20.txt, Chap. 2.6.3:
763                 * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message
764                 * attribute */
765                free(sta->last_eap_radius);
766                sta->last_eap_radius = NULL;
767                sta->last_eap_radius_len = 0;
768                return;
769        }
770
771        if (len < sizeof(*hdr))
772        {
773                free(eap);
774                return;
775        }
776
777        if (len > sizeof(*hdr))
778                eap_type = eap[sizeof(*hdr)];
779
780        hdr = (struct eap_hdr *) eap;
781
782        sta->eapol_sm->be_auth.idFromServer = hdr->identifier;
783
784        if (sta->last_eap_radius)
785                free(sta->last_eap_radius);
786        sta->last_eap_radius = eap;
787        sta->last_eap_radius_len = len;
788}
789
790static void ieee802_1x_get_keys(rtapd *rtapd, struct sta_info *sta,
791                                struct radius_msg *msg, struct radius_msg *req,
792                                u8 *shared_secret, size_t shared_secret_len)
793{
794        struct radius_ms_mppe_keys *keys;
795        NDIS_802_11_KEY         WepKey;
796       
797        memset(&WepKey, 0,sizeof(NDIS_802_11_KEY));
798        keys = Radius_msg_get_ms_keys(msg, req, shared_secret, shared_secret_len);
799       
800        if(keys && keys->recv_len != 0)
801        {
802                /*      draft-ietf-eap-keying-01.txt
803                        Appendix C. MSK and EMSK Hierarchy
804
805                        In EAP-TLS [RFC2716], the MSK is divided into two halves,
806                        corresponding to the "Peer to Authenticator Encryption Key"
807                        (Enc-RECV-Key, 32 octets, also known as the PMK) and "Authenticator
808                        to Peer Encryption Key" (Enc-SEND-Key, 32 octets). In [RFC2548], the
809                        Enc-RECV-Key (the PMK) is transported in the MS-MPPE-Recv-Key
810                        attribute, and the Enc-SEND-Key is transported in the
811                        MS-MPPE-Send-Key attribute.
812                */
813       
814                DBGPRINT(RT_DEBUG_INFO, "IEEE802_1x_Get_Keys, PMK_len = %d\n",keys->recv_len );
815                DBGPRINT(RT_DEBUG_INFO, "PMK = %x %x %x %x %x %x %x ...%x \n",\
816                        keys->recv[0],keys->recv[1],keys->recv[2],keys->recv[3],\
817                        keys->recv[4],keys->recv[5],keys->recv[6],keys->recv[15]);
818                DBGPRINT(RT_DEBUG_INFO, "PMK[16] = %x %x %x %x %x %x %x %x \n",\
819                        keys->recv[16],keys->recv[17],keys->recv[18],keys->recv[19],\
820                        keys->recv[20],keys->recv[21],keys->recv[22],keys->recv[23]);
821
822                WepKey.KeyLength = keys->recv_len;
823                memcpy(WepKey.KeyMaterial, keys->recv, (keys->recv_len== 32?32:1));
824                memcpy(WepKey.addr, sta->addr, 6);
825
826                // WPA2(pre-auth)
827                if (sta->ethertype == ETH_P_PRE_AUTH)
828                {
829                        if (RT_ioctl(rtapd->ioctl_sock,
830                                                 RT_PRIV_IOCTL,
831                                                 (char *)&WepKey,
832                                                 sizeof(NDIS_802_11_KEY),
833                                                 rtapd->prefix_wlan_name, 0,
834                                                 RT_OID_802_DOT1X_PMKID_CACHE))
835                        {
836                                DBGPRINT(RT_DEBUG_ERROR,"ieee802_1x_get_keys:RT_OID_802_DOT1X_PMKID_CACHE\n");
837                                return;
838                        }
839                }
840                else
841                {
842                        if (keys->recv_len == 32 && keys->send_len == 32)
843                        {
844                                WepKey.KeyLength += keys->send_len;
845                                memcpy(&WepKey.KeyMaterial[32], keys->send, 32);
846                        }
847                       
848                        if (RT_ioctl(rtapd->ioctl_sock,
849                                                 RT_PRIV_IOCTL,
850                                                 (char *)&WepKey,
851                                                 sizeof(NDIS_802_11_KEY),
852                                                 rtapd->prefix_wlan_name,
853                                                 sta->ApIdx,
854                                                 RT_OID_802_DOT1X_WPA_KEY))
855                        {
856                                DBGPRINT(RT_DEBUG_ERROR,"ieee802_1x_get_keys:RT_OID_802_DOT1X_WPA_KEY\n");
857                                return;
858                        }
859                }
860
861       
862                if (keys->send && keys->recv)
863                {
864                        free(sta->eapol_key_sign);
865                        free(sta->eapol_key_crypt);
866                        sta->eapol_key_sign = keys->send;
867                        sta->eapol_key_sign_len = keys->send_len;
868                        sta->eapol_key_crypt = keys->recv;
869                        sta->eapol_key_crypt_len = keys->recv_len;
870                        sta->eapol_sm->keyAvailable = TRUE;
871                }
872                else
873                {
874                        free(keys->send);
875                        free(keys->recv);
876                }
877                free(keys);
878        }
879}
880
881#ifdef HAVE_AQOS
882int stricmp( char *a, char *b )
883{
884    int l1 = strlen( a );
885    int l2 = strlen( b );
886
887    if( l1 != l2 )
888        return -1;
889    int i;
890
891    for( i = 0; i < l1; i++ )
892    {
893        if( toupper( a[i] ) != toupper( b[i] ) )
894            return -1;
895    }
896    return 0;
897}
898extern void add_usermac( char *mac, int idx, char *upstream,
899                         char *downstream );
900
901extern char *nvram_safe_get(const char *name);
902
903int addrule( char *mac, char *upstream, char *downstream )
904{
905    char *qos_mac = nvram_safe_get( "svqos_macs" );
906    int ret = 0;
907
908    if( strlen( qos_mac ) > 0 )
909    {
910        char *newqos = malloc( strlen( qos_mac ) * 2 );
911
912        memset( newqos, 0, strlen( qos_mac ) );
913        char level[32], level2[32], level3[32], data[32], type[32];
914
915        do
916        {
917            if( sscanf
918                ( qos_mac, "%31s %31s %31s %31s %31s |", data, level, level2,
919                  type, level3 ) < 5 )
920                break;
921            if( !stricmp( data, mac ) && !strcmp( level, upstream )
922                && !strcmp( level2, downstream ) )
923            {
924                sprintf( newqos, "%s %s %s %s %s %s |", newqos, data, upstream,
925                         downstream, "hostapd", level3 );
926                ret |= 2;
927            }
928            else
929            {
930                if( !stricmp( data, mac ) )
931                {
932                    ret |= 1;
933                }
934                sprintf( newqos, "%s %s %s %s %s %s |", newqos, data, level,
935                         level2, type, level3);
936            }
937        }
938        while( ( qos_mac = strpbrk( ++qos_mac, "|" ) ) && qos_mac++ );
939        nvram_set( "svqos_macs", newqos );
940        free( newqos );
941    }
942    else
943    {
944        char newqos[128];
945
946        sprintf( newqos, "%s %s %s %s %s |", mac, upstream, downstream,
947                 "hostapd", level3);
948        nvram_set( "svqos_macs", newqos );
949    }
950    return ret;
951
952}
953#endif
954
955/* Process the RADIUS frames from Authentication Server */
956static RadiusRxResult
957ieee802_1x_receive_auth(rtapd *rtapd, struct radius_msg *msg, struct radius_msg *req,
958                        u8 *shared_secret, size_t shared_secret_len, void *data)
959{
960        struct sta_info *sta;
961        static int qosidx = 500;
962        u32 session_timeout = 0, idle_timeout = 0, termination_action;
963        int session_timeout_set, idle_timeout_set;
964        int     free_flag = 0;
965
966        DBGPRINT(RT_DEBUG_TRACE,"Receive IEEE802_1X Response Packet From Radius Server. \n");
967
968        sta = Ap_get_sta_radius_identifier(rtapd, msg->hdr->identifier);
969        if (sta == NULL)
970        {
971                return RADIUS_RX_UNKNOWN;
972        }
973
974        /* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be
975         * present when packet contains an EAP-Message attribute */
976        if (msg->hdr->code == RADIUS_CODE_ACCESS_REJECT && Radius_msg_get_attr(msg,
977                RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL, 0) < 0 &&
978                Radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0)
979        {
980        }
981        else if (Radius_msg_verify(msg, shared_secret, shared_secret_len, req))
982        {
983                DBGPRINT(RT_DEBUG_ERROR,"Incoming RADIUS packet did not have correct Message-Authenticator - dropped\n");
984                return RADIUS_RX_UNKNOWN;
985        }
986
987        if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
988                msg->hdr->code != RADIUS_CODE_ACCESS_REJECT &&
989                msg->hdr->code != RADIUS_CODE_ACCESS_CHALLENGE)
990        {
991                DBGPRINT(RT_DEBUG_WARN,"Unknown RADIUS message code\n");
992                return RADIUS_RX_UNKNOWN;
993        }
994
995        sta->radius_identifier = -1;
996
997        if (sta->last_recv_radius)
998        {
999                Radius_msg_free(sta->last_recv_radius);
1000                free(sta->last_recv_radius);
1001        }
1002
1003        sta->last_recv_radius = msg;
1004
1005        /* Extract the Session-Timeout attrubute */
1006        session_timeout_set = !Radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, &session_timeout);
1007
1008        /* Extrace the Termination-Action attribute */
1009        if (Radius_msg_get_attr_int32(msg, RADIUS_ATTR_TERMINATION_ACTION, &termination_action))
1010                termination_action = RADIUS_TERMINATION_ACTION_DEFAULT;
1011
1012        /* Extrace Idle-Timeout attribute */
1013        idle_timeout_set = !Radius_msg_get_attr_int32(msg, RADIUS_ATTR_IDLE_TIMEOUT, &idle_timeout);
1014                       
1015        switch (msg->hdr->code)
1016        {
1017                case RADIUS_CODE_ACCESS_ACCEPT:
1018#ifdef HAVE_AQOS
1019            DBGPRINT(RT_DEBUG_WARN, "check user bandwith shaping\n" );
1020            u32 *down, *up;
1021            size_t len;
1022
1023            if( ( down =
1024                  ( u32 * ) radius_msg_get_vendor_attr( msg,
1025                                                        RADIUS_VENDOR_ID_WISPR,
1026                                                        RADIUS_ATTR_WISPR_BANDWIDTH_MAX_DOWN,
1027                                                        &len ) ) == NULL )
1028            {
1029                DBGPRINT(RT_DEBUG_WARN, "no downstream level found\n" );
1030            }
1031            else
1032            {
1033                if( ( up =
1034                      ( u32 * ) radius_msg_get_vendor_attr( msg,
1035                                                            RADIUS_VENDOR_ID_WISPR,
1036                                                            RADIUS_ATTR_WISPR_BANDWIDTH_MAX_UP,
1037                                                            &len ) ) == NULL )
1038                {
1039                    DBGPRINT(RT_DEBUG_WARN, "no up level found\n" );
1040                    free( down );
1041                }
1042                else
1043                {
1044                    *down = ntohl( *down );
1045                    *up = ntohl( *up );
1046                    DBGPRINT(RT_DEBUG_WARN,
1047                                "downstream %d kbits, upstream %d kbits level found\n",
1048                                *down, *up );
1049                    char mac[64];
1050
1051                    sprintf( mac, MACSTR, MAC2STR( sta->addr ) );
1052                    char uplevel[64];
1053                    char downlevel[64];
1054
1055                    sprintf( uplevel, "%d", *up );
1056                    sprintf( downlevel, "%d", *down );
1057                    int ret = addrule( mac, uplevel, downlevel );
1058
1059                    //case 0 = does not exists, should just be added, no restart
1060                    //case 1 = no change required, already added
1061                    //case 2 = change required, exists, but new settings
1062                    //case 3 = change required, exists, new setting
1063                    if( !ret )
1064                    {
1065                        qosidx += 2;
1066                        if( qosidx > 500 )
1067                            qosidx = 0;
1068                        add_usermac( mac, qosidx, uplevel, downlevel );
1069                    }
1070                    else if( ret > 1 )
1071                    {
1072                        system( "stopservice wshaper" );
1073                        system( "startservice wshaper" );
1074                    }
1075                    free( up );
1076                    free( down );
1077                }
1078
1079            }
1080#endif
1081                        /* draft-congdon-radius-8021x-22.txt, Ch. 3.17 */
1082                        if (session_timeout_set && termination_action == RADIUS_TERMINATION_ACTION_RADIUS_REQUEST)
1083                        {
1084                                DBGPRINT(RT_DEBUG_TRACE,"AP_REAUTH_TIMEOUT %d seconds \n", session_timeout);
1085                                sta->eapol_sm->reauth_timer.reAuthPeriod =      session_timeout;
1086                        }
1087                        else if (session_timeout_set && (rtapd->conf->session_timeout_set == 1))   // 1 1
1088                        {
1089                                Ap_sta_session_timeout(rtapd, sta, ((session_timeout<rtapd->conf->session_timeout_interval) ? session_timeout : rtapd->conf->session_timeout_interval));
1090                        }
1091                        else if (session_timeout_set )   // 1 0
1092                        {
1093                                Ap_sta_session_timeout(rtapd, sta, session_timeout);
1094                        }
1095                        else if (rtapd->conf->session_timeout_set == 1)   // 0 1
1096                        {
1097                                Ap_sta_session_timeout(rtapd, sta, rtapd->conf->session_timeout_interval);
1098                        }
1099                        else  // 0 0
1100                                free_flag = 1;
1101                        sta->eapol_sm->be_auth.aSuccess = TRUE;
1102
1103                        /* Set idle timeout */
1104                        if (idle_timeout_set)
1105                                dot1x_set_IdleTimeoutAction(rtapd, sta, idle_timeout);
1106       
1107                        ieee802_1x_get_keys(rtapd, sta, msg, req, shared_secret, shared_secret_len);
1108                        break;
1109
1110                case RADIUS_CODE_ACCESS_REJECT:
1111                        DBGPRINT(RT_DEBUG_WARN, "AS send RADIUS_CODE_ACCESS_REJECT\n");
1112                        sta->eapol_sm->be_auth.aFail = TRUE;
1113                        break;
1114
1115                case RADIUS_CODE_ACCESS_CHALLENGE:
1116                        if (session_timeout_set)
1117                        {
1118                                /* RFC 2869, Ch. 2.3.2
1119                                 * draft-congdon-radius-8021x-22.txt, Ch. 3.17 */
1120                                sta->eapol_sm->be_auth.suppTimeout = session_timeout;
1121                        }
1122                        sta->eapol_sm->be_auth.aReq = TRUE;
1123                        break;
1124        }
1125
1126        ieee802_1x_decapsulate_radius(sta);
1127        eapol_sm_step(sta->eapol_sm);
1128
1129
1130        if (free_flag == 1)
1131                Ap_free_sta(rtapd, sta);
1132        return RADIUS_RX_QUEUED;
1133}
1134
1135
1136/* Handler for EAPOL Backend Authentication state machine sendRespToServer.
1137 * Forward the EAP Response from Supplicant to Authentication Server. */
1138void ieee802_1x_send_resp_to_server(rtapd *rtapd, struct sta_info *sta)
1139{
1140        ieee802_1x_encapsulate_radius(rtapd, sta, sta->last_eap_supp, sta->last_eap_supp_len);
1141}
1142
1143int ieee802_1x_init(rtapd *rtapd)
1144{
1145        if (Radius_client_register(rtapd, RADIUS_AUTH, ieee802_1x_receive_auth, NULL))
1146                return -1;
1147
1148        return 0;
1149}
1150
1151void ieee802_1x_new_auth_session(rtapd *rtapd, struct sta_info *sta)
1152{
1153        if (!sta->last_recv_radius)
1154                return;
1155
1156        Radius_msg_free(sta->last_recv_radius);
1157        free(sta->last_recv_radius);
1158        sta->last_recv_radius = NULL;
1159}
Note: See TracBrowser for help on using the repository browser.