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
00049 static guint mic_failure_timer_id = 0;
00050
00051
00052 static guint mic_failure_running_timer_id = 0;
00053
00054
00055 static GSList *ap_black_list = NULL;
00056
00057
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
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
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
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
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
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
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
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
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
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
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
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
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
00282 *hdr_p++ = 0;
00283 *hdr_p++ = 0;
00284
00285
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
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
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
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
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
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
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
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
00540
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
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
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
00659
00660
00661
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
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
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
00767
00768
00769
00770
00771
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
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
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 }