wpa.c

Go to the documentation of this file.
00001 
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <stdint.h>
00027 #include <string.h>
00028 #include <sys/ioctl.h>
00029 #include <glib.h>
00030 #include <glib-object.h>
00031 #include <unistd.h>
00032 #include <sys/types.h>
00033 #include <sys/socket.h>
00034 #include <linux/types.h>
00035 #include <linux/netlink.h>
00036 #include <linux/rtnetlink.h>
00037 #include <linux/if_ether.h>
00038 
00039 #define DBUS_API_SUBJECT_TO_CHANGE
00040 #include <dbus/dbus.h>
00041 #include <eap-dbus.h>
00042 
00043 #include "wpa.h"
00044 #include "common.h"
00045 #include "dbus-handler.h"
00046 #include "log.h"
00047 
00048 /* MIC failure timer ID */
00049 static guint mic_failure_timer_id = 0;
00050 
00051 /* MIC failure timer running ID */
00052 static guint mic_failure_running_timer_id = 0;
00053 
00054 /* Black list of APs */
00055 static GSList *ap_black_list = NULL;
00056 
00057 /* Cipher suites */
00058 static const guint8 WPA_CIPHER_SUITE_NONE[] = {0x00, 0x50, 0xf2, 0};
00059 static const guint8 WPA_CIPHER_SUITE_WEP40[] = {0x00, 0x50, 0xf2, 1};
00060 static const guint8 WPA_CIPHER_SUITE_TKIP[] = {0x00, 0x50, 0xf2, 2};
00061 //static const guint8 WPA_CIPHER_SUITE_WRAP[] = {0x00, 0x50, 0xf2, 3};
00062 static const guint8 WPA_CIPHER_SUITE_CCMP[] = {0x00, 0x50, 0xf2, 4};
00063 static const guint8 WPA_CIPHER_SUITE_WEP104[] = {0x00, 0x50, 0xf2, 5};
00064 
00065 static const guint8 RSN_CIPHER_SUITE_NONE[] = {0x00, 0x0f, 0xac, 0};
00066 static const guint8 RSN_CIPHER_SUITE_WEP40[] = {0x00, 0x0f, 0xac, 1};
00067 static const guint8 RSN_CIPHER_SUITE_TKIP[] = {0x00, 0x0f, 0xac, 2};
00068 //static const guint8 RSN_CIPHER_SUITE_WRAP[] = {0x00, 0x0f, 0xac, 3};
00069 static const guint8 RSN_CIPHER_SUITE_CCMP[] = {0x00, 0x0f, 0xac, 4};
00070 static const guint8 RSN_CIPHER_SUITE_WEP104[] = {0x00, 0x0f, 0xac, 5};
00071 
00072 /* Key management suites */
00073 static const guint8 RSN_KEY_MGMT_802_1X[] = {0x00, 0x0f, 0xac, 1};
00074 static const guint8 RSN_KEY_MGMT_PSK[] = {0x00, 0x0f, 0xac, 2};
00075 static const guint8 WPA_KEY_MGMT_802_1X[] = {0x00, 0x50, 0xf2, 1};
00076 static const guint8 WPA_KEY_MGMT_PSK[] = {0x00, 0x50, 0xf2, 2};
00077 
00078 static const guint8 WPA_OUI[] = { 0x00, 0x50, 0xf2 };
00079 
00080 guint parse_rsn_cipher_suite(guint8 *suite)
00081 {
00082         if (memcmp(suite, RSN_CIPHER_SUITE_TKIP, CIPHER_SUITE_LEN) == 0)
00083                 return CIPHER_SUITE_TKIP;
00084         if (memcmp(suite, RSN_CIPHER_SUITE_CCMP, CIPHER_SUITE_LEN) == 0)
00085                 return CIPHER_SUITE_CCMP;
00086         if (memcmp(suite, RSN_CIPHER_SUITE_NONE, CIPHER_SUITE_LEN) == 0)
00087                 return CIPHER_SUITE_NONE;
00088         if (memcmp(suite, RSN_CIPHER_SUITE_WEP40, CIPHER_SUITE_LEN) == 0)
00089                 return CIPHER_SUITE_WEP40;
00090         if (memcmp(suite, RSN_CIPHER_SUITE_WEP104, CIPHER_SUITE_LEN) == 0)
00091                 return CIPHER_SUITE_WEP104;
00092         return 0;
00093 }
00094 
00095 guint parse_rsn_key_mgmt_suite(guint8 *suite)
00096 {
00097         if (memcmp(suite, RSN_KEY_MGMT_802_1X, CIPHER_SUITE_LEN) == 0)
00098                 return WPA_802_1X;
00099         if (memcmp(suite, RSN_KEY_MGMT_PSK, CIPHER_SUITE_LEN) == 0)
00100                 return WPA_PSK;
00101         return 0;
00102 }
00103 
00104 guint parse_wpa_cipher_suite(guint8* suite)
00105 {
00106         if (memcmp(suite, WPA_CIPHER_SUITE_TKIP, CIPHER_SUITE_LEN) == 0)
00107                 return CIPHER_SUITE_TKIP;
00108         if (memcmp(suite, WPA_CIPHER_SUITE_CCMP, CIPHER_SUITE_LEN) == 0)
00109                 return CIPHER_SUITE_CCMP;
00110         if (memcmp(suite, WPA_CIPHER_SUITE_NONE, CIPHER_SUITE_LEN) == 0)
00111                 return CIPHER_SUITE_NONE;
00112         if (memcmp(suite, WPA_CIPHER_SUITE_WEP40, CIPHER_SUITE_LEN) == 0)
00113                 return CIPHER_SUITE_WEP40;
00114         if (memcmp(suite, WPA_CIPHER_SUITE_WEP104, CIPHER_SUITE_LEN) == 0)
00115                 return CIPHER_SUITE_WEP104;
00116         return 0;
00117 }
00118 
00119 guint parse_wpa_key_mgmt_suite(guint8 *suite)
00120 {
00121         if (memcmp(suite, WPA_KEY_MGMT_802_1X, CIPHER_SUITE_LEN) == 0)
00122                 return WPA_802_1X;
00123         if (memcmp(suite, WPA_KEY_MGMT_PSK, CIPHER_SUITE_LEN) == 0)
00124                 return WPA_PSK;
00125         return 0;
00126 }
00133 static int generate_wpa_ie(guint32 encryption, 
00134                            struct wlan_status_t *wlan_status) 
00135 {
00136         guint8 *wpa_ie;
00137         struct wpa_ie_t *wpa_hdr;
00138         guint8* hdr_p;
00139         
00140         /* Update the length if you change something */
00141         wpa_ie = g_malloc(sizeof(struct wpa_ie_t)+4+CIPHER_SUITE_LEN*3);
00142         
00143         wpa_hdr = (struct wpa_ie_t*) wpa_ie;
00144         wpa_hdr->element_id = WPA_ELEMENT;
00145         memcpy(&wpa_hdr->oui, WPA_OUI, sizeof(WPA_OUI));
00146         wpa_hdr->oui_type = 1;
00147         
00148         wpa_hdr->version = WPA_VERSION;
00149         hdr_p = (guint8*)(wpa_hdr + 1);
00150         
00151         /* Group cipher suite */
00152         if (wlan_status->group_cipher == CIPHER_SUITE_TKIP) {
00153                 memcpy(hdr_p, WPA_CIPHER_SUITE_TKIP, CIPHER_SUITE_LEN);
00154         } else if (wlan_status->group_cipher == CIPHER_SUITE_CCMP) {
00155                 memcpy(hdr_p, WPA_CIPHER_SUITE_CCMP, CIPHER_SUITE_LEN);
00156         } else {
00157                 DLOG_ERR("Unsupported group cipher suite");
00158                 return -1;
00159         }
00160         
00161 
00162         hdr_p += CIPHER_SUITE_LEN;
00163 
00164         /* Pairwise count */
00165         *hdr_p++ = 1;
00166         *hdr_p++ = 0;
00167 
00168         if (wlan_status->pairwise_cipher == CIPHER_SUITE_TKIP) {
00169                 memcpy(hdr_p, WPA_CIPHER_SUITE_TKIP, CIPHER_SUITE_LEN);
00170         } else if (wlan_status->pairwise_cipher == CIPHER_SUITE_CCMP) {
00171                 memcpy(hdr_p, WPA_CIPHER_SUITE_CCMP, CIPHER_SUITE_LEN);
00172         }  else {
00173                 DLOG_ERR("Unsupported pairwise cipher suite");
00174                 return -1;
00175         }
00176 
00177         hdr_p += CIPHER_SUITE_LEN;
00178         
00179         /* Authentication count */
00180         *hdr_p++ = 1;
00181         *hdr_p++ = 0;
00182         
00183         if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_PSK) {
00184                 DLOG_DEBUG("WPA PSK selected");
00185                 memcpy(hdr_p, WPA_KEY_MGMT_PSK, CIPHER_SUITE_LEN); 
00186         } else if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == 
00187                    WLANCOND_WPA_EAP) {
00188                 DLOG_DEBUG("WPA EAP selected");
00189                 memcpy(hdr_p, WPA_KEY_MGMT_802_1X, CIPHER_SUITE_LEN);
00190         } else {
00191                 DLOG_ERR("Unknown key management suite");
00192                 return 1;
00193         }
00194         
00195         hdr_p += CIPHER_SUITE_LEN;
00196 
00197         /* Capabilities are empty */
00198 
00199         wpa_hdr->length = (hdr_p - wpa_ie) - 2;
00200 
00201 #ifdef DEBUG_IE
00202         int i;
00203         printf("Own WPA IE:\n");
00204         for (i=0;i<wpa_hdr->length;i++) {
00205                 printf("0x%02x ", wpa_ie[i]);
00206         }
00207         printf("\n");
00208 #endif        
00209 
00210         update_own_ie(wpa_ie, wpa_hdr->length + 2);
00211 
00212         return 0;
00213 }
00220 static int generate_wpa2_ie(guint32 encryption, 
00221                             struct wlan_status_t *wlan_status) 
00222 {
00223         
00224         guint8 *wpa_ie;
00225         struct rsn_ie_t *wpa_hdr;
00226         guint8* hdr_p;
00227         
00228         /* Update the length if you change something */
00229         wpa_ie = g_malloc(sizeof(struct rsn_ie_t)+8+CIPHER_SUITE_LEN*3+
00230                           IW_PMKID_LEN);
00231         
00232         wpa_hdr = (struct rsn_ie_t*) wpa_ie;
00233         wpa_hdr->element_id = RSN_ELEMENT;
00234         
00235         wpa_hdr->version = RSN_VERSION;
00236         hdr_p = (guint8*)(wpa_hdr + 1);
00237         
00238         /* Group cipher suite */
00239         if (wlan_status->group_cipher == CIPHER_SUITE_TKIP) {
00240                 memcpy(hdr_p, RSN_CIPHER_SUITE_TKIP, CIPHER_SUITE_LEN);
00241         } else if (wlan_status->group_cipher == CIPHER_SUITE_CCMP) {
00242                 memcpy(hdr_p, RSN_CIPHER_SUITE_CCMP, CIPHER_SUITE_LEN);
00243         } else {
00244                 DLOG_ERR("Unsupported group cipher suite");
00245                 return -1;
00246         }
00247 
00248         hdr_p += CIPHER_SUITE_LEN;
00249 
00250         /* Pairwise count */
00251         *hdr_p++ = 1;
00252         *hdr_p++ = 0;
00253 
00254         if (wlan_status->pairwise_cipher == CIPHER_SUITE_TKIP) {
00255                 memcpy(hdr_p, RSN_CIPHER_SUITE_TKIP, CIPHER_SUITE_LEN);
00256         } else if (wlan_status->pairwise_cipher == CIPHER_SUITE_CCMP) {
00257                 memcpy(hdr_p, RSN_CIPHER_SUITE_CCMP, CIPHER_SUITE_LEN);
00258         } else {
00259                 DLOG_ERR("Unsupported pairwise cipher suite");
00260                 return -1;
00261         }
00262         
00263         hdr_p += CIPHER_SUITE_LEN;
00264         
00265         /* Authentication count */
00266         *hdr_p++ = 1;
00267         *hdr_p++ = 0;
00268         
00269         if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_PSK) {
00270                 memcpy(hdr_p, RSN_KEY_MGMT_PSK, CIPHER_SUITE_LEN); 
00271         } else if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == 
00272                    WLANCOND_WPA_EAP){
00273                 memcpy(hdr_p, RSN_KEY_MGMT_802_1X, CIPHER_SUITE_LEN);
00274         } else {
00275                 DLOG_ERR("Unknown key management suite");
00276                 return -1;
00277         }
00278         
00279         hdr_p += CIPHER_SUITE_LEN;
00280         
00281         /* Capabilities are empty */
00282         *hdr_p++ = 0;
00283         *hdr_p++ = 0;
00284 
00285         /* PMKID */
00286         unsigned char *pmkid = find_pmkid_from_pmk_cache(
00287                 wlan_status->conn.bssid);
00288         if (pmkid != NULL) {
00289                 *hdr_p++ = 1;
00290                 *hdr_p++ = 0;
00291                 memcpy(hdr_p, pmkid, IW_PMKID_LEN);
00292                 hdr_p += IW_PMKID_LEN;
00293         }
00294 
00295         wpa_hdr->length = (hdr_p - wpa_ie) - 2;
00296         
00297 #ifdef DEBUG_IE
00298         int i;
00299         printf("Own WPA IE:\n");
00300         for (i=0;i<wpa_hdr->length;i++) {
00301                 printf("0x%02x ", wpa_ie[i]);
00302         }
00303         printf("\n");
00304 #endif        
00305         
00306         update_own_ie(wpa_ie, wpa_hdr->length + 2);
00307         
00308         return 0;
00309 }
00316 static int set_wpa_ie(struct wlan_status_t *wlan_status)
00317 {
00318         struct iwreq req;
00319         
00320         DLOG_DEBUG("Setting IE, len:%d", wlan_status->wpa_ie.ie_len);
00321         
00322         init_iwreq(&req);
00323         
00324         req.u.data.pointer = (caddr_t) wlan_status->wpa_ie.ie;
00325         req.u.data.length = wlan_status->wpa_ie.ie_len;
00326         
00327         if (ioctl(socket_open(), SIOCSIWGENIE, &req) < 0) {
00328                 DLOG_ERR("Set WPA IE failed\n");
00329                 return -1;
00330         }
00331 
00332         return 0;
00333 }
00334 
00335 /* Fixme, add WEP40 support !!!
00336   */
00337 static guint32 pairwise_encryption_to_cipher(guint32 encryption)
00338 {
00339         if ((encryption & WLANCOND_ENCRYPT_ALG_MASK) == WLANCOND_WPA_TKIP)
00340                 return IW_AUTH_CIPHER_TKIP;
00341         if ((encryption & WLANCOND_ENCRYPT_ALG_MASK) == WLANCOND_WPA_AES)
00342                 return IW_AUTH_CIPHER_CCMP;
00343         if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP)
00344                 return IW_AUTH_CIPHER_WEP104;
00345         return IW_AUTH_CIPHER_NONE;
00346 }
00347 
00348  /* Fixme, add WEP40 support !!!
00349   */
00350 static guint32 group_encryption_to_cipher(guint32 encryption)
00351 {
00352         if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) == 
00353             WLANCOND_WPA_TKIP_GROUP)
00354                 return IW_AUTH_CIPHER_TKIP;
00355         if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) == 
00356             (guint32)WLANCOND_WPA_AES_GROUP)
00357                 return IW_AUTH_CIPHER_CCMP;
00358         if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP)
00359                 return IW_AUTH_CIPHER_WEP104;
00360         return IW_AUTH_CIPHER_NONE;
00361 }
00368 static int set_encryption_method_helper(gint index, guint32 value)
00369 {
00370         struct iwreq req;
00371         
00372         init_iwreq(&req);
00373 
00374         DLOG_DEBUG("Setting param %d, value: 0x%X", index, value);
00375         
00376         req.u.param.flags = index & IW_AUTH_INDEX;
00377         req.u.param.value = value;
00378         
00379         if (ioctl(socket_open(), SIOCSIWAUTH, &req) < 0) {
00380                 DLOG_ERR("Could not set auth mode %d, %X", index, value);
00381                 return -1;
00382         }
00383         
00384         return 0;
00385 }
00391 int set_countermeasures(guint on_off) 
00392 {
00393         return set_encryption_method_helper(IW_AUTH_TKIP_COUNTERMEASURES, 
00394                                             on_off);
00395 }
00396 
00403 gboolean set_encryption_method(guint32 encryption, 
00404                                struct wlan_status_t *wlan_status) 
00405 {
00406         guint32 value = 0;
00407         guint32 key_mgmt = 0;
00408         gboolean wpa2 = FALSE;
00409         guint32 authentication = wlan_status->conn.authentication_type;
00410 
00411         if (encryption & WLANCOND_ENCRYPT_WPA2_MASK)
00412                 wpa2 = TRUE;
00413         
00414         if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_PSK) {
00415                 if (wpa2 == TRUE)
00416                         value = IW_AUTH_WPA_VERSION_WPA2;
00417                 else
00418                         value = IW_AUTH_WPA_VERSION_WPA;
00419                 key_mgmt = IW_AUTH_KEY_MGMT_PSK;
00420                 
00421         } else if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_EAP) {
00422                 if (wpa2 == TRUE)
00423                         value = IW_AUTH_WPA_VERSION_WPA2;
00424                 else
00425                         value = IW_AUTH_WPA_VERSION_WPA;
00426                 key_mgmt = IW_AUTH_KEY_MGMT_802_1X;
00427         } else {
00428                 value = IW_AUTH_WPA_VERSION_DISABLED;
00429         }
00430         
00431         if (key_mgmt != 0) {
00432                 if (set_encryption_method_helper(IW_AUTH_WPA_ENABLED, 1) < 0)
00433                         return FALSE;
00434 
00435                 set_encryption_method_helper(IW_AUTH_DROP_UNENCRYPTED,
00436                                              1);
00437                 
00438                 set_encryption_method_helper(IW_AUTH_80211_AUTH_ALG,
00439                                              IW_AUTH_ALG_OPEN_SYSTEM);
00440                 
00441         }
00442         
00443         if (set_encryption_method_helper(IW_AUTH_WPA_VERSION, value) < 0)
00444                 return FALSE;
00445 
00446         if (key_mgmt != 0) {
00447                 // Set Information Element if not WPS mode
00448                 if (authentication != EAP_AUTH_TYPE_WFA_SC) {
00449                         if (wpa2 == TRUE)
00450                                 value = generate_wpa2_ie(encryption, wlan_status);
00451                         else
00452                                 value = generate_wpa_ie(encryption, wlan_status);
00453                 }
00454         } else {
00455                 if (set_encryption_method_helper(IW_AUTH_WPA_ENABLED, 0) < 0)
00456                         return FALSE;
00457                 
00458                 /* Check for WEP */
00459                 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) != WLANCOND_WEP)
00460                         set_encryption_method_helper(IW_AUTH_DROP_UNENCRYPTED, 
00461                                                      0);
00462         }
00463         if (value < 0)
00464                 return FALSE;
00465         
00466         /* Set IE */
00467         if (set_wpa_ie(wlan_status) <0)
00468                 return FALSE;
00469         
00470         value = pairwise_encryption_to_cipher(encryption);
00471 
00472         if (set_encryption_method_helper(IW_AUTH_CIPHER_PAIRWISE, value) < 0)
00473                 return FALSE;
00474         
00475         value = group_encryption_to_cipher(encryption);
00476         
00477         if (set_encryption_method_helper(IW_AUTH_CIPHER_GROUP, value) < 0)
00478                 return FALSE;
00479 
00480         if (set_encryption_method_helper(IW_AUTH_KEY_MGMT, key_mgmt) < 0)
00481                 return FALSE;
00482         
00483         value = key_mgmt != 0 || 
00484                 (encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP;
00485         
00486         if (set_encryption_method_helper(IW_AUTH_PRIVACY_INVOKED, value) < 0) {
00487                 /* Ignore error in Adhoc */
00488                 if (wlan_status->conn.mode != WLANCOND_ADHOC)
00489                         return FALSE;
00490         }
00491         
00492         if (key_mgmt != 0) {
00493                 value = 0;
00494         } else {
00495                 value = 1;
00496         }
00497 
00498         if (set_encryption_method_helper(IW_AUTH_RX_UNENCRYPTED_EAPOL,
00499                                          value) < 0)
00500                 return FALSE;
00501 
00502         return TRUE;
00503 }
00504 
00505 gint compare_bssid(gconstpointer a, gconstpointer b) 
00506 {
00507         return memcmp(a, b, ETH_ALEN);
00508 }
00509 
00514 static void remove_ap_from_black_list(unsigned char* bssid) 
00515 {
00516         GSList *list;
00517 
00518         list = g_slist_find_custom(ap_black_list, bssid, &compare_bssid);
00519         
00520         if (list != NULL) {
00521                 unsigned char* bssid_entry = (unsigned char*)list->data;
00522                 print_mac("Found black list entry to be removed:", 
00523                           bssid);
00524                         
00525                 /* Remove the old entry */
00526                 ap_black_list = g_slist_remove(ap_black_list, 
00527                                                bssid_entry);
00528                 g_free(bssid_entry);
00529         }
00530 }
00531 
00537 static gboolean mic_failure_timer_cb(void* data) 
00538 {
00539         /* Since we get into this function no MIC failure
00540            has happened within last 60 seconds.
00541         */
00542         mic_failure_timer_id = 0;
00543         
00544         DLOG_DEBUG("No MIC failures within the last 60 seconds.");
00545 
00546         if (data != NULL) {
00547                 remove_ap_from_black_list(data);
00548         }
00549 
00550         return FALSE;
00551 }
00552 
00558 gboolean is_ap_in_black_list(unsigned char* bssid) 
00559 {
00560         GSList *list; 
00561         
00562         list = g_slist_find_custom(ap_black_list, bssid, &compare_bssid);
00563         
00564         if (list != NULL) {
00565                 print_mac("Found AP from black list:", bssid);
00566                 return TRUE;
00567         }
00568         return FALSE;
00569 }  
00570 
00576 static gboolean mic_failure_running_cb(void* data) 
00577 {
00578         mic_failure_running_timer_id = 0;
00579         
00580         DLOG_DEBUG("MIC failures off");
00581 
00582         if (data != NULL) {
00583                 remove_ap_from_black_list(data);
00584         }
00585         
00586         return FALSE;
00587 }
00588 
00589 static void add_ap_to_black_list(unsigned char* bssid) 
00590 {
00591         ap_black_list = g_slist_prepend(ap_black_list, 
00592                                         g_memdup(bssid, ETH_ALEN));
00593 }
00594         
00595 
00601 int handle_mic_failure(gboolean key_type, unsigned char* bssid) 
00602 {        
00603         
00604         if (mic_failure_timer_id != 0) {
00605 
00606                 g_source_remove(mic_failure_timer_id);
00607                 mic_failure_timer_id = 0;
00608 
00609                 /* Second failure in 60 seconds, fatal */                
00610                 wpa_mic_failure_event(key_type, TRUE);
00611                 
00612                 DLOG_ERR("Second MIC failure, AP is disconnected");
00613 
00614                 sleep(1);
00615 
00616                 mlme_command(bssid, IW_MLME_DEAUTH, 
00617                              WLANCOND_REASON_MIC_FAILURE);
00618                 
00619                 set_wlan_state(WLAN_NOT_INITIALIZED,
00620                                DISCONNECTED_SIGNAL,
00621                                FORCE_NO);
00622 
00623                 /* Set timer to remember this fatal error for 60 seconds */
00624                 mic_failure_running_timer_id = g_timeout_add(
00625                         MIC_FAILURE_TIMEOUT,
00626                         mic_failure_running_cb,
00627                         bssid);
00628 
00629                 add_ap_to_black_list(bssid);
00630                 
00631                 return 0;
00632         }
00633         
00634         wpa_mic_failure_event(key_type, FALSE);
00635         
00636         mic_failure_timer_id = g_timeout_add(MIC_FAILURE_TIMEOUT,
00637                                              mic_failure_timer_cb,
00638                                              bssid);
00639         return 0;
00640 }
00641 
00649 int parse_rsn_ie(unsigned char* wpa_ie, unsigned int wpa_ie_len,
00650                  struct ap_info_t* ap_info) 
00651 {
00652         struct rsn_ie_t *wpa_hdr;
00653         guint8 *hdr_p;
00654         guint ind;
00655         guint i;
00656         guint cipher_count = 0;
00657         
00658         /* Do data checking, we have to make sure all the time that we
00659            don't go past the IE length , index variable counts the 
00660            remaining data, the spec says that all data after the version 
00661            field is optional */
00662 
00663         wpa_hdr = (struct rsn_ie_t*) wpa_ie;
00664         
00665 #if 0 // These are checked already
00666         if (wpa_ie_len < sizeof(struct rsn_ie_t)) {
00667                 DLOG_ERR("WPA IE too short");
00668                 return -1;
00669         }
00670         
00671         if (wpa_hdr->element_id != RSN_ELEMENT) {
00672                 DLOG_ERR("Unknown WPA IE received");
00673                 return -1;
00674         }
00675 #endif        
00676         ind = wpa_ie_len - sizeof(*wpa_hdr);
00677         hdr_p = (guint8*)(wpa_hdr + 1);
00678         
00679         if (ind >= CIPHER_SUITE_LEN) {
00680                 ap_info->group_cipher = parse_rsn_cipher_suite(hdr_p);
00681                 hdr_p += CIPHER_SUITE_LEN;
00682                 ind -= CIPHER_SUITE_LEN;
00683         } else {
00684                 DLOG_ERR("Strange length in WPA IE");
00685                 return -1;
00686         }
00687         
00688         if (ind >= 2) {
00689                 ap_info->pairwise_cipher = 0;
00690                 cipher_count = *(guint16*)hdr_p;
00691                 
00692                 ind -= 2;
00693                 
00694                 if (cipher_count == 0) {
00695                         DLOG_ERR("No pairwise ciphers");
00696                         // Return 0 instead or an error
00697                         return 0;
00698                 }
00699 
00700                 if (ind < cipher_count * CIPHER_SUITE_LEN) {
00701                         DLOG_ERR("Invalid pairwise cipher length");
00702                         return -1;
00703                 }
00704 
00705                 hdr_p += 2;
00706                 
00707                 for (i = 0; i < cipher_count; i++) {
00708                         ap_info->pairwise_cipher |= parse_rsn_cipher_suite(hdr_p);
00709                         ind -= CIPHER_SUITE_LEN;
00710                         hdr_p += CIPHER_SUITE_LEN;
00711                 }
00712         } else if (ind == 1) {
00713                 DLOG_ERR("Remaining data too short");
00714                 return -1;
00715         }
00716 
00717         if (ind >= 2) {
00718                 ap_info->key_mgmt = 0;
00719                 cipher_count = *(guint16*)hdr_p;
00720                 hdr_p += 2;
00721                 ind -= 2;
00722                 
00723                 if (cipher_count == 0 || ind < cipher_count *
00724                     CIPHER_SUITE_LEN) {
00725                         DLOG_ERR("Invalid key mgmt cipher count or length");
00726                         return -1;
00727                 }
00728                 
00729                 for (i = 0; i < cipher_count; i++) {
00730                         ap_info->key_mgmt |= parse_rsn_key_mgmt_suite(hdr_p);
00731                         ind -= CIPHER_SUITE_LEN;
00732                         hdr_p += CIPHER_SUITE_LEN;
00733                 }
00734         } else if (ind == 1) {
00735                 DLOG_ERR("Remaining data too short");
00736                 return -1;
00737         }
00738         
00739         if (ind >= 2) {
00740                 //ap_info->rsn_capabilities = *(guint16*)hdr_p;
00741                 hdr_p += 2;
00742                 ind -= 2;
00743         }
00744         
00745         if (ind > 0) {
00746                 DLOG_DEBUG("IE includes PMKID data");
00747         }
00748         return 0;
00749 }
00750 
00751 
00759 int parse_wpa_ie(unsigned char* wpa_ie, unsigned int wpa_ie_len,
00760                  struct ap_info_t* ap_info) 
00761 {
00762         struct wpa_ie_t *wpa_hdr;
00763         guint8 *hdr_p;
00764         guint ind, i;
00765         guint cipher_count = 0;
00766         //const guint8 WPA1_OUI[] = { 0x00, 0x50, 0xf2, 1 };
00767         
00768         /* Do data checking, we have to make sure all the time that we
00769            don't go past the IE length , index variable counts the 
00770            remaining data, the spec says that all data after the version 
00771            field is optional */
00772 
00773         wpa_hdr = (struct wpa_ie_t*) wpa_ie;
00774 
00775 #if 0 // These are checked already
00776         if (wpa_ie_len < sizeof(struct wpa_ie_t)) {
00777                 DLOG_ERR("WPA IE too short");
00778                 return -1;
00779         }
00780         
00781         if (wpa_hdr->element_id != WPA_ELEMENT) {
00782                 DLOG_ERR("Unknown WPA IE received");
00783                 return -1;
00784         }
00785         
00786         if (memcmp(&wpa_hdr->oui, WPA1_OUI, CIPHER_SUITE_LEN) != 0) {
00787                 DLOG_ERR("Invalid WPA header");
00788                 return -1;
00789         }
00790 #endif        
00791         ind = wpa_ie_len - sizeof(*wpa_hdr);
00792         hdr_p = (guint8*)(wpa_hdr + 1);
00793 
00794         if (ind >= CIPHER_SUITE_LEN) {
00795                 ap_info->group_cipher = parse_wpa_cipher_suite(hdr_p);
00796                 ind -= CIPHER_SUITE_LEN;
00797                 hdr_p += CIPHER_SUITE_LEN;
00798         } else {
00799                 DLOG_ERR("Strange length in WPA IE");
00800                 return -1;
00801         }
00802         
00803         if (ind >= 2) {
00804                 ap_info->pairwise_cipher = 0;
00805                 cipher_count = *(guint16*)hdr_p;
00806                 ind -= 2;
00807                  
00808                 if (cipher_count == 0) {
00809                         DLOG_ERR("No pairwise ciphers");
00810                         // Return 0 instead or an error
00811                         return 0;
00812                 }
00813 
00814                 if (ind < cipher_count * CIPHER_SUITE_LEN) {
00815                         DLOG_ERR("Invalid pairwise cipher length");
00816                         return -1;
00817                 }
00818                 
00819                 hdr_p += 2;
00820                 
00821                 for (i = 0; i < cipher_count; i++) {
00822                         ap_info->pairwise_cipher |= parse_wpa_cipher_suite(hdr_p);
00823                         ind -= CIPHER_SUITE_LEN;
00824                         hdr_p += CIPHER_SUITE_LEN;
00825                 }
00826         } else if (ind == 1) {
00827                 DLOG_ERR("Remaining data too short");
00828                 return -1;
00829         }
00830 
00831         if (ind >= 2) {
00832                 ap_info->key_mgmt = 0;
00833                 cipher_count = *(guint16*)hdr_p;
00834                 hdr_p += 2;
00835                 ind -= 2;
00836                 
00837                 if (cipher_count == 0 || ind < cipher_count *
00838                     CIPHER_SUITE_LEN) {
00839                         DLOG_ERR("Invalid key mgmt cipher count (%d) or length", cipher_count);
00840                         return -1;
00841                 }
00842                 
00843                 for (i = 0; i < cipher_count; i++) {
00844                         ap_info->key_mgmt |= parse_wpa_key_mgmt_suite(hdr_p);
00845                         ind -= CIPHER_SUITE_LEN;
00846                         hdr_p += CIPHER_SUITE_LEN;
00847                 }
00848         } else if (ind == 1) {
00849                 DLOG_ERR("Remaining data too short");
00850                 return -1;
00851         }
00852         
00853         if (ind >= 2) {
00854                 //ap_info->rsn_capabilities = *(guint16*)hdr_p;
00855                 hdr_p += 2;
00856                 ind -= 2;
00857         }
00858         
00859         if (ind > 0) {
00860                 DLOG_ERR("IE too long?");
00861                 return -1;
00862         }
00863         return 0;
00864 }

Generated on Sat Dec 6 22:17:00 2008 for WLAN Connection Daemon by  doxygen 1.5.1