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 static 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 static 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 static 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 static 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 g_free(wpa_ie);
00159 return -1;
00160 }
00161
00162
00163 hdr_p += CIPHER_SUITE_LEN;
00164
00165
00166 *hdr_p++ = 1;
00167 *hdr_p++ = 0;
00168
00169 if (wlan_status->pairwise_cipher == CIPHER_SUITE_TKIP) {
00170 memcpy(hdr_p, WPA_CIPHER_SUITE_TKIP, CIPHER_SUITE_LEN);
00171 } else if (wlan_status->pairwise_cipher == CIPHER_SUITE_CCMP) {
00172 memcpy(hdr_p, WPA_CIPHER_SUITE_CCMP, CIPHER_SUITE_LEN);
00173 } else {
00174 DLOG_ERR("Unsupported pairwise cipher suite");
00175 g_free(wpa_ie);
00176 return -1;
00177 }
00178
00179 hdr_p += CIPHER_SUITE_LEN;
00180
00181
00182 *hdr_p++ = 1;
00183 *hdr_p++ = 0;
00184
00185 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_PSK) {
00186 DLOG_DEBUG("WPA PSK selected");
00187 memcpy(hdr_p, WPA_KEY_MGMT_PSK, CIPHER_SUITE_LEN);
00188 } else if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) ==
00189 WLANCOND_WPA_EAP) {
00190 DLOG_DEBUG("WPA EAP selected");
00191 memcpy(hdr_p, WPA_KEY_MGMT_802_1X, CIPHER_SUITE_LEN);
00192 } else {
00193 DLOG_ERR("Unknown key management suite");
00194 g_free(wpa_ie);
00195 return 1;
00196 }
00197
00198 hdr_p += CIPHER_SUITE_LEN;
00199
00200
00201
00202 wpa_hdr->length = (hdr_p - wpa_ie) - 2;
00203
00204 #ifdef DEBUG_IE
00205 int i;
00206 printf("Own WPA IE:\n");
00207 for (i=0;i<wpa_hdr->length;i++) {
00208 printf("0x%02x ", wpa_ie[i]);
00209 }
00210 printf("\n");
00211 #endif
00212
00213 update_own_ie(wpa_ie, wpa_hdr->length + 2);
00214
00215 return 0;
00216 }
00223 static int generate_wpa2_ie(guint32 encryption,
00224 struct wlan_status_t *wlan_status)
00225 {
00226
00227 guint8 *wpa_ie;
00228 struct rsn_ie_t *wpa_hdr;
00229 guint8* hdr_p;
00230
00231
00232 wpa_ie = g_malloc(sizeof(struct rsn_ie_t)+8+CIPHER_SUITE_LEN*3+
00233 IW_PMKID_LEN);
00234
00235 wpa_hdr = (struct rsn_ie_t*) wpa_ie;
00236 wpa_hdr->element_id = RSN_ELEMENT;
00237
00238 wpa_hdr->version = RSN_VERSION;
00239 hdr_p = (guint8*)(wpa_hdr + 1);
00240
00241
00242 if (wlan_status->group_cipher == CIPHER_SUITE_TKIP) {
00243 memcpy(hdr_p, RSN_CIPHER_SUITE_TKIP, CIPHER_SUITE_LEN);
00244 } else if (wlan_status->group_cipher == CIPHER_SUITE_CCMP) {
00245 memcpy(hdr_p, RSN_CIPHER_SUITE_CCMP, CIPHER_SUITE_LEN);
00246 } else {
00247 DLOG_ERR("Unsupported group cipher suite");
00248 g_free(wpa_ie);
00249 return -1;
00250 }
00251
00252 hdr_p += CIPHER_SUITE_LEN;
00253
00254
00255 *hdr_p++ = 1;
00256 *hdr_p++ = 0;
00257
00258 if (wlan_status->pairwise_cipher == CIPHER_SUITE_TKIP) {
00259 memcpy(hdr_p, RSN_CIPHER_SUITE_TKIP, CIPHER_SUITE_LEN);
00260 } else if (wlan_status->pairwise_cipher == CIPHER_SUITE_CCMP) {
00261 memcpy(hdr_p, RSN_CIPHER_SUITE_CCMP, CIPHER_SUITE_LEN);
00262 } else {
00263 DLOG_ERR("Unsupported pairwise cipher suite");
00264 g_free(wpa_ie);
00265 return -1;
00266 }
00267
00268 hdr_p += CIPHER_SUITE_LEN;
00269
00270
00271 *hdr_p++ = 1;
00272 *hdr_p++ = 0;
00273
00274 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_PSK) {
00275 memcpy(hdr_p, RSN_KEY_MGMT_PSK, CIPHER_SUITE_LEN);
00276 } else if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) ==
00277 WLANCOND_WPA_EAP){
00278 memcpy(hdr_p, RSN_KEY_MGMT_802_1X, CIPHER_SUITE_LEN);
00279 } else {
00280 DLOG_ERR("Unknown key management suite");
00281 g_free(wpa_ie);
00282 return -1;
00283 }
00284
00285 hdr_p += CIPHER_SUITE_LEN;
00286
00287
00288 *hdr_p++ = 0;
00289 *hdr_p++ = 0;
00290
00291
00292 unsigned char *pmkid;
00293
00294 if (find_pmkid_from_pmk_cache(wlan_status->conn.bssid, &pmkid)) {
00295 DLOG_ERR("Error trying to retrieve the pmkid.");
00296 return ESUPPLICANT;
00297 }
00298
00299 if (pmkid != NULL) {
00300 *hdr_p++ = 1;
00301 *hdr_p++ = 0;
00302 memcpy(hdr_p, pmkid, IW_PMKID_LEN);
00303 hdr_p += IW_PMKID_LEN;
00304 }
00305
00306 wpa_hdr->length = (hdr_p - wpa_ie) - 2;
00307
00308 #ifdef DEBUG_IE
00309 int i;
00310 printf("Own WPA IE:\n");
00311 for (i=0;i<wpa_hdr->length;i++) {
00312 printf("0x%02x ", wpa_ie[i]);
00313 }
00314 printf("\n");
00315 #endif
00316
00317 update_own_ie(wpa_ie, wpa_hdr->length + 2);
00318
00319 return 0;
00320 }
00327 int set_wpa_ie(struct wlan_status_t *wlan_status)
00328 {
00329 struct iwreq req;
00330
00331 DLOG_DEBUG("Setting IE, len:%d", wlan_status->wpa_ie.ie_len);
00332
00333 init_iwreq(&req);
00334
00335 req.u.data.pointer = (caddr_t) wlan_status->wpa_ie.ie;
00336 req.u.data.length = wlan_status->wpa_ie.ie_len;
00337
00338 if (ioctl(socket_open(), SIOCSIWGENIE, &req) < 0) {
00339 DLOG_ERR("Set WPA IE failed\n");
00340 return -1;
00341 }
00342
00343 return 0;
00344 }
00345
00346
00347
00348 static guint32 pairwise_encryption_to_cipher(guint32 encryption)
00349 {
00350 if ((encryption & WLANCOND_ENCRYPT_ALG_MASK) == WLANCOND_WPA_TKIP)
00351 return IW_AUTH_CIPHER_TKIP;
00352 if ((encryption & WLANCOND_ENCRYPT_ALG_MASK) == WLANCOND_WPA_AES)
00353 return IW_AUTH_CIPHER_CCMP;
00354 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP)
00355 return IW_AUTH_CIPHER_WEP104;
00356 return IW_AUTH_CIPHER_NONE;
00357 }
00358
00359
00360
00361 static guint32 group_encryption_to_cipher(guint32 encryption)
00362 {
00363 if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) ==
00364 WLANCOND_WPA_TKIP_GROUP)
00365 return IW_AUTH_CIPHER_TKIP;
00366 if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) ==
00367 (guint32)WLANCOND_WPA_AES_GROUP)
00368 return IW_AUTH_CIPHER_CCMP;
00369 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP)
00370 return IW_AUTH_CIPHER_WEP104;
00371 return IW_AUTH_CIPHER_NONE;
00372 }
00379 static int set_encryption_method_helper(gint index, guint32 value)
00380 {
00381 struct iwreq req;
00382
00383 init_iwreq(&req);
00384
00385
00386
00387 req.u.param.flags = index & IW_AUTH_INDEX;
00388 req.u.param.value = value;
00389
00390 if (ioctl(socket_open(), SIOCSIWAUTH, &req) < 0) {
00391 DLOG_ERR("Could not set auth mode %d, %X", index, value);
00392 return -1;
00393 }
00394
00395 return 0;
00396 }
00402 int set_countermeasures(guint on_off)
00403 {
00404 return set_encryption_method_helper(IW_AUTH_TKIP_COUNTERMEASURES,
00405 on_off);
00406 }
00407
00414 gint set_encryption_method(guint32 encryption,
00415 struct wlan_status_t *wlan_status)
00416 {
00417 gint32 value = 0;
00418 guint32 key_mgmt = 0;
00419 gboolean wpa2 = FALSE;
00420 guint32 authentication = wlan_status->conn.authentication_type;
00421
00422 if (encryption & WLANCOND_ENCRYPT_WPA2_MASK)
00423 wpa2 = TRUE;
00424
00425 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_PSK) {
00426 if (wpa2 == TRUE)
00427 value = IW_AUTH_WPA_VERSION_WPA2;
00428 else
00429 value = IW_AUTH_WPA_VERSION_WPA;
00430 key_mgmt = IW_AUTH_KEY_MGMT_PSK;
00431
00432 } else if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) ==
00433 WLANCOND_WPA_EAP) {
00434 if (wpa2 == TRUE)
00435 value = IW_AUTH_WPA_VERSION_WPA2;
00436 else
00437 value = IW_AUTH_WPA_VERSION_WPA;
00438 key_mgmt = IW_AUTH_KEY_MGMT_802_1X;
00439 } else {
00440 value = IW_AUTH_WPA_VERSION_DISABLED;
00441 }
00442
00443 if (key_mgmt != 0) {
00444 if (set_encryption_method_helper(IW_AUTH_WPA_ENABLED, 1) < 0)
00445 return -1;
00446
00447 set_encryption_method_helper(IW_AUTH_DROP_UNENCRYPTED,
00448 1);
00449
00450 set_encryption_method_helper(IW_AUTH_80211_AUTH_ALG,
00451 IW_AUTH_ALG_OPEN_SYSTEM);
00452
00453 }
00454
00455 if (set_encryption_method_helper(IW_AUTH_WPA_VERSION, value) < 0)
00456 return -1;
00457
00458 if (key_mgmt != 0) {
00459
00460 if (authentication != EAP_AUTH_TYPE_WFA_SC) {
00461 if (wpa2 == TRUE)
00462 value = generate_wpa2_ie(encryption,
00463 wlan_status);
00464 else
00465 value = generate_wpa_ie(encryption,
00466 wlan_status);
00467 }
00468 } else {
00469 if (set_encryption_method_helper(IW_AUTH_WPA_ENABLED, 0) < 0)
00470 return -1;
00471
00472
00473 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) != WLANCOND_WEP){
00474 set_encryption_method_helper(IW_AUTH_DROP_UNENCRYPTED,
00475 0);
00476 } else {
00477
00478 set_encryption_method_helper(IW_AUTH_80211_AUTH_ALG,
00479 IW_AUTH_ALG_OPEN_SYSTEM|IW_AUTH_ALG_SHARED_KEY);
00480 }
00481
00482 }
00483 if (value < 0)
00484 return value;
00485
00486
00487 if (set_wpa_ie(wlan_status) <0)
00488 return -1;
00489
00490 value = pairwise_encryption_to_cipher(encryption);
00491
00492 if (set_encryption_method_helper(IW_AUTH_CIPHER_PAIRWISE, value) < 0)
00493 return -1;
00494
00495 value = group_encryption_to_cipher(encryption);
00496
00497 if (set_encryption_method_helper(IW_AUTH_CIPHER_GROUP, value) < 0)
00498 return -1;
00499
00500 if (set_encryption_method_helper(IW_AUTH_KEY_MGMT, key_mgmt) < 0)
00501 return -1;
00502
00503 value = key_mgmt != 0 ||
00504 (encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP;
00505
00506 if (set_encryption_method_helper(IW_AUTH_PRIVACY_INVOKED, value) < 0) {
00507
00508 if (wlan_status->conn.mode != WLANCOND_ADHOC)
00509 return -1;
00510 }
00511
00512 if (key_mgmt != 0) {
00513 value = 0;
00514 } else {
00515 value = 1;
00516 }
00517
00518 if (set_encryption_method_helper(IW_AUTH_RX_UNENCRYPTED_EAPOL,
00519 value) < 0)
00520 return -1;
00521
00522 return 0;
00523 }
00524
00525 static gint compare_bssid(gconstpointer a, gconstpointer b)
00526 {
00527 return memcmp(a, b, ETH_ALEN);
00528 }
00529
00534 static void remove_ap_from_black_list(unsigned char* bssid)
00535 {
00536 GSList *list;
00537
00538 list = g_slist_find_custom(ap_black_list, bssid, &compare_bssid);
00539
00540 if (list != NULL) {
00541 unsigned char* bssid_entry = list->data;
00542 print_mac(WLANCOND_PRIO_MEDIUM,
00543 "Found black list entry to be removed:",
00544 bssid);
00545
00546
00547 ap_black_list = g_slist_remove(ap_black_list,
00548 bssid_entry);
00549 g_free(bssid_entry);
00550 }
00551 }
00552
00558 static gboolean mic_failure_timer_cb(void* data)
00559 {
00560
00561
00562
00563 mic_failure_timer_id = 0;
00564
00565 print_mac(WLANCOND_PRIO_MEDIUM,
00566 "No MIC failures within the last 60 seconds for:",
00567 data);
00568
00569 remove_ap_from_black_list(data);
00570
00571 return FALSE;
00572 }
00573
00579 gboolean is_ap_in_black_list(unsigned char* bssid)
00580 {
00581 GSList *list;
00582
00583 list = g_slist_find_custom(ap_black_list, bssid, &compare_bssid);
00584
00585 if (list != NULL) {
00586 print_mac(WLANCOND_PRIO_HIGH,
00587 "Found AP from black list:", bssid);
00588 return TRUE;
00589 }
00590 return FALSE;
00591 }
00592
00598 static gboolean mic_failure_running_cb(void* data)
00599 {
00600 mic_failure_running_timer_id = 0;
00601
00602 print_mac(WLANCOND_PRIO_HIGH, "MIC failures off for:", data);
00603
00604 remove_ap_from_black_list(data);
00605
00606 return FALSE;
00607 }
00608
00609 static void add_ap_to_black_list(unsigned char* bssid)
00610 {
00611 ap_black_list = g_slist_prepend(ap_black_list,
00612 g_memdup(bssid, ETH_ALEN));
00613 }
00614
00615 static void mic_destroy_cb(gpointer data)
00616 {
00617
00618 g_free(data);
00619 }
00620
00626 int handle_mic_failure(gboolean key_type, unsigned char* bssid)
00627 {
00628
00629 if (mic_failure_timer_id != 0) {
00630
00631 g_source_remove(mic_failure_timer_id);
00632 mic_failure_timer_id = 0;
00633
00634
00635 wpa_mic_failure_event(key_type, TRUE);
00636
00637 print_mac(WLANCOND_PRIO_HIGH,
00638 "Second MIC failure, disconnecting AP:", bssid);
00639
00640 sleep(1);
00641
00642 mlme_command(bssid, IW_MLME_DEAUTH,
00643 WLANCOND_REASON_MIC_FAILURE);
00644
00645 set_wlan_state(WLAN_NOT_INITIALIZED,
00646 DISCONNECTED_SIGNAL,
00647 FORCE_NO);
00648
00649
00650 mic_failure_running_timer_id = g_timeout_add_seconds_full(
00651 G_PRIORITY_DEFAULT,
00652 MIC_FAILURE_TIMEOUT,
00653 mic_failure_running_cb,
00654 g_memdup(bssid, ETH_ALEN),
00655 mic_destroy_cb);
00656
00657 add_ap_to_black_list(bssid);
00658
00659 return 0;
00660 }
00661
00662 wpa_mic_failure_event(key_type, FALSE);
00663
00664 mic_failure_timer_id = g_timeout_add_seconds_full(
00665 G_PRIORITY_DEFAULT,
00666 MIC_FAILURE_TIMEOUT,
00667 mic_failure_timer_cb,
00668 g_memdup(bssid, ETH_ALEN),
00669 mic_destroy_cb);
00670
00671 return 0;
00672 }
00673
00681 int parse_rsn_ie(unsigned char* wpa_ie, unsigned int wpa_ie_len,
00682 struct ap_info_t* ap_info)
00683 {
00684 struct rsn_ie_t *wpa_hdr;
00685 guint8 *hdr_p;
00686 guint ind;
00687 guint i;
00688 guint cipher_count = 0;
00689
00690
00691
00692
00693
00694
00695 wpa_hdr = (struct rsn_ie_t*) wpa_ie;
00696
00697 if (wpa_ie_len < sizeof(struct rsn_ie_t)) {
00698 DLOG_ERR("WPA IE too short");
00699 return -1;
00700 }
00701
00702 if (wpa_hdr->element_id != RSN_ELEMENT) {
00703 DLOG_ERR("Unknown WPA IE received");
00704 return -1;
00705 }
00706
00707 ind = wpa_ie_len - sizeof(*wpa_hdr);
00708 hdr_p = (guint8*)(wpa_hdr + 1);
00709
00710 if (ind >= CIPHER_SUITE_LEN) {
00711 ap_info->group_cipher = parse_rsn_cipher_suite(hdr_p);
00712 hdr_p += CIPHER_SUITE_LEN;
00713 ind -= CIPHER_SUITE_LEN;
00714 } else {
00715 DLOG_ERR("Strange length in WPA IE");
00716 return -1;
00717 }
00718
00719 if (ind >= 2) {
00720 ap_info->pairwise_cipher = 0;
00721 cipher_count = *(guint16*)hdr_p;
00722
00723 ind -= 2;
00724
00725 if (cipher_count == 0) {
00726 DLOG_ERR("No pairwise ciphers");
00727
00728 return 0;
00729 }
00730
00731 if (ind < cipher_count * CIPHER_SUITE_LEN) {
00732 DLOG_ERR("Invalid pairwise cipher length");
00733 return -1;
00734 }
00735
00736 hdr_p += 2;
00737
00738 for (i = 0; i < cipher_count; i++) {
00739 ap_info->pairwise_cipher |= parse_rsn_cipher_suite(hdr_p);
00740 ind -= CIPHER_SUITE_LEN;
00741 hdr_p += CIPHER_SUITE_LEN;
00742 }
00743 } else if (ind == 1) {
00744 DLOG_ERR("Remaining data too short");
00745 return -1;
00746 }
00747
00748 if (ind >= 2) {
00749 ap_info->key_mgmt = 0;
00750 cipher_count = *(guint16*)hdr_p;
00751 hdr_p += 2;
00752 ind -= 2;
00753
00754 if (cipher_count == 0 || ind < cipher_count *
00755 CIPHER_SUITE_LEN) {
00756 DLOG_ERR("Invalid key mgmt cipher count or length");
00757 return -1;
00758 }
00759
00760 for (i = 0; i < cipher_count; i++) {
00761 ap_info->key_mgmt |= parse_rsn_key_mgmt_suite(hdr_p);
00762 ind -= CIPHER_SUITE_LEN;
00763 hdr_p += CIPHER_SUITE_LEN;
00764 }
00765 } else if (ind == 1) {
00766 DLOG_ERR("Remaining data too short");
00767 return -1;
00768 }
00769
00770 if (ind >= 2) {
00771
00772 hdr_p += 2;
00773 ind -= 2;
00774 }
00775
00776 if (ind > 0) {
00777 DLOG_DEBUG("IE includes PMKID data");
00778 }
00779 return 0;
00780 }
00781
00782
00790 int parse_wpa_ie(unsigned char* wpa_ie, unsigned int wpa_ie_len,
00791 struct ap_info_t* ap_info)
00792 {
00793 struct wpa_ie_t *wpa_hdr;
00794 guint8 *hdr_p;
00795 guint ind, i;
00796 guint cipher_count = 0;
00797 const guint8 WPA1_OUI[] = { 0x00, 0x50, 0xf2, 1 };
00798
00799
00800
00801
00802
00803
00804 wpa_hdr = (struct wpa_ie_t*) wpa_ie;
00805
00806 if (wpa_ie_len < sizeof(struct wpa_ie_t)) {
00807 DLOG_ERR("WPA IE too short");
00808 return -1;
00809 }
00810
00811 if (wpa_hdr->element_id != WPA_ELEMENT) {
00812 DLOG_ERR("Unknown WPA IE received");
00813 return -1;
00814 }
00815
00816 if (memcmp(&wpa_hdr->oui, WPA1_OUI, CIPHER_SUITE_LEN) != 0) {
00817 DLOG_ERR("Invalid WPA header");
00818 return -1;
00819 }
00820
00821 ind = wpa_ie_len - sizeof(*wpa_hdr);
00822 hdr_p = (guint8*)(wpa_hdr + 1);
00823
00824 if (ind >= CIPHER_SUITE_LEN) {
00825 ap_info->group_cipher = parse_wpa_cipher_suite(hdr_p);
00826 ind -= CIPHER_SUITE_LEN;
00827 hdr_p += CIPHER_SUITE_LEN;
00828 } else {
00829 DLOG_ERR("Strange length in WPA IE");
00830 return -1;
00831 }
00832
00833 if (ind >= 2) {
00834 ap_info->pairwise_cipher = 0;
00835 cipher_count = *(guint16*)hdr_p;
00836 ind -= 2;
00837
00838 if (cipher_count == 0) {
00839 DLOG_ERR("No pairwise ciphers");
00840
00841 return 0;
00842 }
00843
00844 if (ind < cipher_count * CIPHER_SUITE_LEN) {
00845 DLOG_ERR("Invalid pairwise cipher length");
00846 return -1;
00847 }
00848
00849 hdr_p += 2;
00850
00851 for (i = 0; i < cipher_count; i++) {
00852 ap_info->pairwise_cipher |=
00853 parse_wpa_cipher_suite(hdr_p);
00854 ind -= CIPHER_SUITE_LEN;
00855 hdr_p += CIPHER_SUITE_LEN;
00856 }
00857 } else if (ind == 1) {
00858 DLOG_ERR("Remaining data too short");
00859 return -1;
00860 }
00861
00862 if (ind >= 2) {
00863 ap_info->key_mgmt = 0;
00864 cipher_count = *(guint16*)hdr_p;
00865 hdr_p += 2;
00866 ind -= 2;
00867
00868 if (cipher_count == 0 || ind < cipher_count *
00869 CIPHER_SUITE_LEN) {
00870 DLOG_ERR("Invalid key mgmt cipher count (%d) or length",
00871 cipher_count);
00872 return -1;
00873 }
00874
00875 for (i = 0; i < cipher_count; i++) {
00876 ap_info->key_mgmt |= parse_wpa_key_mgmt_suite(hdr_p);
00877 ind -= CIPHER_SUITE_LEN;
00878 hdr_p += CIPHER_SUITE_LEN;
00879 }
00880 } else if (ind == 1) {
00881 DLOG_ERR("Remaining data too short");
00882 return -1;
00883 }
00884
00885 if (ind >= 2) {
00886
00887 hdr_p += 2;
00888 ind -= 2;
00889 }
00890
00891 if (ind > 0) {
00892 DLOG_ERR("IE too long?");
00893 return -1;
00894 }
00895 return 0;
00896 }