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 = find_pmkid_from_pmk_cache(
00293 wlan_status->conn.bssid);
00294 if (pmkid != NULL) {
00295 *hdr_p++ = 1;
00296 *hdr_p++ = 0;
00297 memcpy(hdr_p, pmkid, IW_PMKID_LEN);
00298 hdr_p += IW_PMKID_LEN;
00299 }
00300
00301 wpa_hdr->length = (hdr_p - wpa_ie) - 2;
00302
00303 #ifdef DEBUG_IE
00304 int i;
00305 printf("Own WPA IE:\n");
00306 for (i=0;i<wpa_hdr->length;i++) {
00307 printf("0x%02x ", wpa_ie[i]);
00308 }
00309 printf("\n");
00310 #endif
00311
00312 update_own_ie(wpa_ie, wpa_hdr->length + 2);
00313
00314 return 0;
00315 }
00322 int set_wpa_ie(struct wlan_status_t *wlan_status)
00323 {
00324 struct iwreq req;
00325
00326 DLOG_DEBUG("Setting IE, len:%d", wlan_status->wpa_ie.ie_len);
00327
00328 init_iwreq(&req);
00329
00330 req.u.data.pointer = (caddr_t) wlan_status->wpa_ie.ie;
00331 req.u.data.length = wlan_status->wpa_ie.ie_len;
00332
00333 if (ioctl(socket_open(), SIOCSIWGENIE, &req) < 0) {
00334 DLOG_ERR("Set WPA IE failed\n");
00335 return -1;
00336 }
00337
00338 return 0;
00339 }
00340
00341
00342
00343 static guint32 pairwise_encryption_to_cipher(guint32 encryption)
00344 {
00345 if ((encryption & WLANCOND_ENCRYPT_ALG_MASK) == WLANCOND_WPA_TKIP)
00346 return IW_AUTH_CIPHER_TKIP;
00347 if ((encryption & WLANCOND_ENCRYPT_ALG_MASK) == WLANCOND_WPA_AES)
00348 return IW_AUTH_CIPHER_CCMP;
00349 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP)
00350 return IW_AUTH_CIPHER_WEP104;
00351 return IW_AUTH_CIPHER_NONE;
00352 }
00353
00354
00355
00356 static guint32 group_encryption_to_cipher(guint32 encryption)
00357 {
00358 if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) ==
00359 WLANCOND_WPA_TKIP_GROUP)
00360 return IW_AUTH_CIPHER_TKIP;
00361 if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) ==
00362 (guint32)WLANCOND_WPA_AES_GROUP)
00363 return IW_AUTH_CIPHER_CCMP;
00364 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP)
00365 return IW_AUTH_CIPHER_WEP104;
00366 return IW_AUTH_CIPHER_NONE;
00367 }
00374 static int set_encryption_method_helper(gint index, guint32 value)
00375 {
00376 struct iwreq req;
00377
00378 init_iwreq(&req);
00379
00380
00381
00382 req.u.param.flags = index & IW_AUTH_INDEX;
00383 req.u.param.value = value;
00384
00385 if (ioctl(socket_open(), SIOCSIWAUTH, &req) < 0) {
00386 DLOG_ERR("Could not set auth mode %d, %X", index, value);
00387 return -1;
00388 }
00389
00390 return 0;
00391 }
00397 int set_countermeasures(guint on_off)
00398 {
00399 return set_encryption_method_helper(IW_AUTH_TKIP_COUNTERMEASURES,
00400 on_off);
00401 }
00402
00409 gboolean set_encryption_method(guint32 encryption,
00410 struct wlan_status_t *wlan_status)
00411 {
00412 gint32 value = 0;
00413 guint32 key_mgmt = 0;
00414 gboolean wpa2 = FALSE;
00415 guint32 authentication = wlan_status->conn.authentication_type;
00416
00417 if (encryption & WLANCOND_ENCRYPT_WPA2_MASK)
00418 wpa2 = TRUE;
00419
00420 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_PSK) {
00421 if (wpa2 == TRUE)
00422 value = IW_AUTH_WPA_VERSION_WPA2;
00423 else
00424 value = IW_AUTH_WPA_VERSION_WPA;
00425 key_mgmt = IW_AUTH_KEY_MGMT_PSK;
00426
00427 } else if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_EAP) {
00428 if (wpa2 == TRUE)
00429 value = IW_AUTH_WPA_VERSION_WPA2;
00430 else
00431 value = IW_AUTH_WPA_VERSION_WPA;
00432 key_mgmt = IW_AUTH_KEY_MGMT_802_1X;
00433 } else {
00434 value = IW_AUTH_WPA_VERSION_DISABLED;
00435 }
00436
00437 if (key_mgmt != 0) {
00438 if (set_encryption_method_helper(IW_AUTH_WPA_ENABLED, 1) < 0)
00439 return FALSE;
00440
00441 set_encryption_method_helper(IW_AUTH_DROP_UNENCRYPTED,
00442 1);
00443
00444 set_encryption_method_helper(IW_AUTH_80211_AUTH_ALG,
00445 IW_AUTH_ALG_OPEN_SYSTEM);
00446
00447 }
00448
00449 if (set_encryption_method_helper(IW_AUTH_WPA_VERSION, value) < 0)
00450 return FALSE;
00451
00452 if (key_mgmt != 0) {
00453
00454 if (authentication != EAP_AUTH_TYPE_WFA_SC) {
00455 if (wpa2 == TRUE)
00456 value = generate_wpa2_ie(encryption, wlan_status);
00457 else
00458 value = generate_wpa_ie(encryption, wlan_status);
00459 }
00460 } else {
00461 if (set_encryption_method_helper(IW_AUTH_WPA_ENABLED, 0) < 0)
00462 return FALSE;
00463
00464
00465 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) != WLANCOND_WEP)
00466 set_encryption_method_helper(IW_AUTH_DROP_UNENCRYPTED,
00467 0);
00468 }
00469 if (value < 0)
00470 return FALSE;
00471
00472
00473 if (set_wpa_ie(wlan_status) <0)
00474 return FALSE;
00475
00476 value = pairwise_encryption_to_cipher(encryption);
00477
00478 if (set_encryption_method_helper(IW_AUTH_CIPHER_PAIRWISE, value) < 0)
00479 return FALSE;
00480
00481 value = group_encryption_to_cipher(encryption);
00482
00483 if (set_encryption_method_helper(IW_AUTH_CIPHER_GROUP, value) < 0)
00484 return FALSE;
00485
00486 if (set_encryption_method_helper(IW_AUTH_KEY_MGMT, key_mgmt) < 0)
00487 return FALSE;
00488
00489 value = key_mgmt != 0 ||
00490 (encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP;
00491
00492 if (set_encryption_method_helper(IW_AUTH_PRIVACY_INVOKED, value) < 0) {
00493
00494 if (wlan_status->conn.mode != WLANCOND_ADHOC)
00495 return FALSE;
00496 }
00497
00498 if (key_mgmt != 0) {
00499 value = 0;
00500 } else {
00501 value = 1;
00502 }
00503
00504 if (set_encryption_method_helper(IW_AUTH_RX_UNENCRYPTED_EAPOL,
00505 value) < 0)
00506 return FALSE;
00507
00508 return TRUE;
00509 }
00510
00511 static gint compare_bssid(gconstpointer a, gconstpointer b)
00512 {
00513 return memcmp(a, b, ETH_ALEN);
00514 }
00515
00520 static void remove_ap_from_black_list(unsigned char* bssid)
00521 {
00522 GSList *list;
00523
00524 list = g_slist_find_custom(ap_black_list, bssid, &compare_bssid);
00525
00526 if (list != NULL) {
00527 unsigned char* bssid_entry = list->data;
00528 print_mac("Found black list entry to be removed:",
00529 bssid);
00530
00531
00532 ap_black_list = g_slist_remove(ap_black_list,
00533 bssid_entry);
00534 g_free(bssid_entry);
00535 }
00536 }
00537
00543 static gboolean mic_failure_timer_cb(void* data)
00544 {
00545
00546
00547
00548 mic_failure_timer_id = 0;
00549
00550 print_mac("No MIC failures within the last 60 seconds for:", data);
00551
00552 remove_ap_from_black_list(data);
00553
00554 return FALSE;
00555 }
00556
00562 gboolean is_ap_in_black_list(unsigned char* bssid)
00563 {
00564 GSList *list;
00565
00566 list = g_slist_find_custom(ap_black_list, bssid, &compare_bssid);
00567
00568 if (list != NULL) {
00569 print_mac("Found AP from black list:", bssid);
00570 return TRUE;
00571 }
00572 return FALSE;
00573 }
00574
00580 static gboolean mic_failure_running_cb(void* data)
00581 {
00582 mic_failure_running_timer_id = 0;
00583
00584 print_mac("MIC failures off for:", data);
00585
00586 remove_ap_from_black_list(data);
00587
00588 return FALSE;
00589 }
00590
00591 static void add_ap_to_black_list(unsigned char* bssid)
00592 {
00593 ap_black_list = g_slist_prepend(ap_black_list,
00594 g_memdup(bssid, ETH_ALEN));
00595 }
00596
00597 static void mic_destroy_cb(gpointer data)
00598 {
00599
00600 g_free(data);
00601 }
00602
00608 int handle_mic_failure(gboolean key_type, unsigned char* bssid)
00609 {
00610
00611 if (mic_failure_timer_id != 0) {
00612
00613 g_source_remove(mic_failure_timer_id);
00614 mic_failure_timer_id = 0;
00615
00616
00617 wpa_mic_failure_event(key_type, TRUE);
00618
00619 print_mac("Second MIC failure, disconnecting AP:", bssid);
00620
00621 sleep(1);
00622
00623 mlme_command(bssid, IW_MLME_DEAUTH,
00624 WLANCOND_REASON_MIC_FAILURE);
00625
00626 set_wlan_state(WLAN_NOT_INITIALIZED,
00627 DISCONNECTED_SIGNAL,
00628 FORCE_NO);
00629
00630
00631 mic_failure_running_timer_id = g_timeout_add_seconds_full(
00632 G_PRIORITY_DEFAULT,
00633 MIC_FAILURE_TIMEOUT,
00634 mic_failure_running_cb,
00635 g_memdup(bssid, ETH_ALEN),
00636 mic_destroy_cb);
00637
00638 add_ap_to_black_list(bssid);
00639
00640 return 0;
00641 }
00642
00643 wpa_mic_failure_event(key_type, FALSE);
00644
00645 mic_failure_timer_id = g_timeout_add_seconds_full(
00646 G_PRIORITY_DEFAULT,
00647 MIC_FAILURE_TIMEOUT,
00648 mic_failure_timer_cb,
00649 g_memdup(bssid, ETH_ALEN),
00650 mic_destroy_cb);
00651
00652 return 0;
00653 }
00654
00662 int parse_rsn_ie(unsigned char* wpa_ie, unsigned int wpa_ie_len,
00663 struct ap_info_t* ap_info)
00664 {
00665 struct rsn_ie_t *wpa_hdr;
00666 guint8 *hdr_p;
00667 guint ind;
00668 guint i;
00669 guint cipher_count = 0;
00670
00671
00672
00673
00674
00675
00676 wpa_hdr = (struct rsn_ie_t*) wpa_ie;
00677
00678 if (wpa_ie_len < sizeof(struct rsn_ie_t)) {
00679 DLOG_ERR("WPA IE too short");
00680 return -1;
00681 }
00682
00683 if (wpa_hdr->element_id != RSN_ELEMENT) {
00684 DLOG_ERR("Unknown WPA IE received");
00685 return -1;
00686 }
00687
00688 ind = wpa_ie_len - sizeof(*wpa_hdr);
00689 hdr_p = (guint8*)(wpa_hdr + 1);
00690
00691 if (ind >= CIPHER_SUITE_LEN) {
00692 ap_info->group_cipher = parse_rsn_cipher_suite(hdr_p);
00693 hdr_p += CIPHER_SUITE_LEN;
00694 ind -= CIPHER_SUITE_LEN;
00695 } else {
00696 DLOG_ERR("Strange length in WPA IE");
00697 return -1;
00698 }
00699
00700 if (ind >= 2) {
00701 ap_info->pairwise_cipher = 0;
00702 cipher_count = *(guint16*)hdr_p;
00703
00704 ind -= 2;
00705
00706 if (cipher_count == 0) {
00707 DLOG_ERR("No pairwise ciphers");
00708
00709 return 0;
00710 }
00711
00712 if (ind < cipher_count * CIPHER_SUITE_LEN) {
00713 DLOG_ERR("Invalid pairwise cipher length");
00714 return -1;
00715 }
00716
00717 hdr_p += 2;
00718
00719 for (i = 0; i < cipher_count; i++) {
00720 ap_info->pairwise_cipher |= parse_rsn_cipher_suite(hdr_p);
00721 ind -= CIPHER_SUITE_LEN;
00722 hdr_p += CIPHER_SUITE_LEN;
00723 }
00724 } else if (ind == 1) {
00725 DLOG_ERR("Remaining data too short");
00726 return -1;
00727 }
00728
00729 if (ind >= 2) {
00730 ap_info->key_mgmt = 0;
00731 cipher_count = *(guint16*)hdr_p;
00732 hdr_p += 2;
00733 ind -= 2;
00734
00735 if (cipher_count == 0 || ind < cipher_count *
00736 CIPHER_SUITE_LEN) {
00737 DLOG_ERR("Invalid key mgmt cipher count or length");
00738 return -1;
00739 }
00740
00741 for (i = 0; i < cipher_count; i++) {
00742 ap_info->key_mgmt |= parse_rsn_key_mgmt_suite(hdr_p);
00743 ind -= CIPHER_SUITE_LEN;
00744 hdr_p += CIPHER_SUITE_LEN;
00745 }
00746 } else if (ind == 1) {
00747 DLOG_ERR("Remaining data too short");
00748 return -1;
00749 }
00750
00751 if (ind >= 2) {
00752
00753 hdr_p += 2;
00754 ind -= 2;
00755 }
00756
00757 if (ind > 0) {
00758 DLOG_DEBUG("IE includes PMKID data");
00759 }
00760 return 0;
00761 }
00762
00763
00771 int parse_wpa_ie(unsigned char* wpa_ie, unsigned int wpa_ie_len,
00772 struct ap_info_t* ap_info)
00773 {
00774 struct wpa_ie_t *wpa_hdr;
00775 guint8 *hdr_p;
00776 guint ind, i;
00777 guint cipher_count = 0;
00778 const guint8 WPA1_OUI[] = { 0x00, 0x50, 0xf2, 1 };
00779
00780
00781
00782
00783
00784
00785 wpa_hdr = (struct wpa_ie_t*) wpa_ie;
00786
00787 if (wpa_ie_len < sizeof(struct wpa_ie_t)) {
00788 DLOG_ERR("WPA IE too short");
00789 return -1;
00790 }
00791
00792 if (wpa_hdr->element_id != WPA_ELEMENT) {
00793 DLOG_ERR("Unknown WPA IE received");
00794 return -1;
00795 }
00796
00797 if (memcmp(&wpa_hdr->oui, WPA1_OUI, CIPHER_SUITE_LEN) != 0) {
00798 DLOG_ERR("Invalid WPA header");
00799 return -1;
00800 }
00801
00802 ind = wpa_ie_len - sizeof(*wpa_hdr);
00803 hdr_p = (guint8*)(wpa_hdr + 1);
00804
00805 if (ind >= CIPHER_SUITE_LEN) {
00806 ap_info->group_cipher = parse_wpa_cipher_suite(hdr_p);
00807 ind -= CIPHER_SUITE_LEN;
00808 hdr_p += CIPHER_SUITE_LEN;
00809 } else {
00810 DLOG_ERR("Strange length in WPA IE");
00811 return -1;
00812 }
00813
00814 if (ind >= 2) {
00815 ap_info->pairwise_cipher = 0;
00816 cipher_count = *(guint16*)hdr_p;
00817 ind -= 2;
00818
00819 if (cipher_count == 0) {
00820 DLOG_ERR("No pairwise ciphers");
00821
00822 return 0;
00823 }
00824
00825 if (ind < cipher_count * CIPHER_SUITE_LEN) {
00826 DLOG_ERR("Invalid pairwise cipher length");
00827 return -1;
00828 }
00829
00830 hdr_p += 2;
00831
00832 for (i = 0; i < cipher_count; i++) {
00833 ap_info->pairwise_cipher |= parse_wpa_cipher_suite(hdr_p);
00834 ind -= CIPHER_SUITE_LEN;
00835 hdr_p += CIPHER_SUITE_LEN;
00836 }
00837 } else if (ind == 1) {
00838 DLOG_ERR("Remaining data too short");
00839 return -1;
00840 }
00841
00842 if (ind >= 2) {
00843 ap_info->key_mgmt = 0;
00844 cipher_count = *(guint16*)hdr_p;
00845 hdr_p += 2;
00846 ind -= 2;
00847
00848 if (cipher_count == 0 || ind < cipher_count *
00849 CIPHER_SUITE_LEN) {
00850 DLOG_ERR("Invalid key mgmt cipher count (%d) or length", cipher_count);
00851 return -1;
00852 }
00853
00854 for (i = 0; i < cipher_count; i++) {
00855 ap_info->key_mgmt |= parse_wpa_key_mgmt_suite(hdr_p);
00856 ind -= CIPHER_SUITE_LEN;
00857 hdr_p += CIPHER_SUITE_LEN;
00858 }
00859 } else if (ind == 1) {
00860 DLOG_ERR("Remaining data too short");
00861 return -1;
00862 }
00863
00864 if (ind >= 2) {
00865
00866 hdr_p += 2;
00867 ind -= 2;
00868 }
00869
00870 if (ind > 0) {
00871 DLOG_ERR("IE too long?");
00872 return -1;
00873 }
00874 return 0;
00875 }