• Main Page
  • Data Structures
  • Files
  • File List
  • Globals

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 #define WLANCOND_AUTH_WPA_VERSION_DISABLED 0x00000001
00049 #define WLANCOND_AUTH_WPA_VERSION_WPA      0x00000002
00050 #define WLANCOND_AUTH_WPA_VERSION_WPA2     0x00000004
00051 #define WLANCOND_AUTH_KEY_MGMT_802_1X      1
00052 #define WLANCOND_AUTH_KEY_MGMT_PSK         2
00053 
00054 /* MIC failure timer ID */
00055 static guint mic_failure_timer_id = 0;
00056 
00057 /* MIC failure timer running ID */
00058 static guint mic_failure_running_timer_id = 0;
00059 
00060 /* Black list of APs */
00061 static GSList *ap_black_list = NULL;
00062 
00063 /* Cipher suites */
00064 static const guint8 WPA_CIPHER_SUITE_NONE[] = {0x00, 0x50, 0xf2, 0};
00065 static const guint8 WPA_CIPHER_SUITE_WEP40[] = {0x00, 0x50, 0xf2, 1};
00066 static const guint8 WPA_CIPHER_SUITE_TKIP[] = {0x00, 0x50, 0xf2, 2};
00067 //static const guint8 WPA_CIPHER_SUITE_WRAP[] = {0x00, 0x50, 0xf2, 3};
00068 static const guint8 WPA_CIPHER_SUITE_CCMP[] = {0x00, 0x50, 0xf2, 4};
00069 static const guint8 WPA_CIPHER_SUITE_WEP104[] = {0x00, 0x50, 0xf2, 5};
00070 
00071 static const guint8 RSN_CIPHER_SUITE_NONE[] = {0x00, 0x0f, 0xac, 0};
00072 static const guint8 RSN_CIPHER_SUITE_WEP40[] = {0x00, 0x0f, 0xac, 1};
00073 static const guint8 RSN_CIPHER_SUITE_TKIP[] = {0x00, 0x0f, 0xac, 2};
00074 //static const guint8 RSN_CIPHER_SUITE_WRAP[] = {0x00, 0x0f, 0xac, 3};
00075 static const guint8 RSN_CIPHER_SUITE_CCMP[] = {0x00, 0x0f, 0xac, 4};
00076 static const guint8 RSN_CIPHER_SUITE_WEP104[] = {0x00, 0x0f, 0xac, 5};
00077 
00078 /* Key management suites */
00079 static const guint8 RSN_KEY_MGMT_802_1X[] = {0x00, 0x0f, 0xac, 1};
00080 static const guint8 RSN_KEY_MGMT_PSK[] = {0x00, 0x0f, 0xac, 2};
00081 static const guint8 WPA_KEY_MGMT_802_1X[] = {0x00, 0x50, 0xf2, 1};
00082 static const guint8 WPA_KEY_MGMT_PSK[] = {0x00, 0x50, 0xf2, 2};
00083 
00084 static const guint8 WPA_OUI[] = { 0x00, 0x50, 0xf2 };
00085 
00086 static guint parse_rsn_cipher_suite(guint8 *suite)
00087 {
00088         if (memcmp(suite, RSN_CIPHER_SUITE_TKIP, CIPHER_SUITE_LEN) == 0)
00089                 return CIPHER_SUITE_TKIP;
00090         if (memcmp(suite, RSN_CIPHER_SUITE_CCMP, CIPHER_SUITE_LEN) == 0)
00091                 return CIPHER_SUITE_CCMP;
00092         if (memcmp(suite, RSN_CIPHER_SUITE_NONE, CIPHER_SUITE_LEN) == 0)
00093                 return CIPHER_SUITE_NONE;
00094         if (memcmp(suite, RSN_CIPHER_SUITE_WEP40, CIPHER_SUITE_LEN) == 0)
00095                 return CIPHER_SUITE_WEP40;
00096         if (memcmp(suite, RSN_CIPHER_SUITE_WEP104, CIPHER_SUITE_LEN) == 0)
00097                 return CIPHER_SUITE_WEP104;
00098         return 0;
00099 }
00100 
00101 static guint parse_rsn_key_mgmt_suite(guint8 *suite)
00102 {
00103         if (memcmp(suite, RSN_KEY_MGMT_802_1X, CIPHER_SUITE_LEN) == 0)
00104                 return WLANCOND_WPA_EAP;
00105         if (memcmp(suite, RSN_KEY_MGMT_PSK, CIPHER_SUITE_LEN) == 0)
00106                 return WLANCOND_WPA_PSK;
00107         return 0;
00108 }
00109 
00110 static guint parse_wpa_cipher_suite(guint8* suite)
00111 {
00112         if (memcmp(suite, WPA_CIPHER_SUITE_TKIP, CIPHER_SUITE_LEN) == 0)
00113                 return CIPHER_SUITE_TKIP;
00114         if (memcmp(suite, WPA_CIPHER_SUITE_CCMP, CIPHER_SUITE_LEN) == 0)
00115                 return CIPHER_SUITE_CCMP;
00116         if (memcmp(suite, WPA_CIPHER_SUITE_NONE, CIPHER_SUITE_LEN) == 0)
00117                 return CIPHER_SUITE_NONE;
00118         if (memcmp(suite, WPA_CIPHER_SUITE_WEP40, CIPHER_SUITE_LEN) == 0)
00119                 return CIPHER_SUITE_WEP40;
00120         if (memcmp(suite, WPA_CIPHER_SUITE_WEP104, CIPHER_SUITE_LEN) == 0)
00121                 return CIPHER_SUITE_WEP104;
00122         return 0;
00123 }
00124 
00125 static guint parse_wpa_key_mgmt_suite(guint8 *suite)
00126 {
00127         if (memcmp(suite, WPA_KEY_MGMT_802_1X, CIPHER_SUITE_LEN) == 0)
00128                 return WLANCOND_WPA_EAP;
00129         if (memcmp(suite, WPA_KEY_MGMT_PSK, CIPHER_SUITE_LEN) == 0)
00130                 return WLANCOND_WPA_PSK;
00131         return 0;
00132 }
00139 static int generate_wpa_ie(guint32 encryption,
00140                 struct wlan_status_t *wlan_status)
00141 {
00142         guint8 *wpa_ie;
00143         struct wpa_ie_t *wpa_hdr;
00144         guint8* hdr_p;
00145 
00146         /* Update the length if you change something */
00147         wpa_ie = g_malloc(sizeof(struct wpa_ie_t)+4+CIPHER_SUITE_LEN*3);
00148 
00149         wpa_hdr = (struct wpa_ie_t*) wpa_ie;
00150         wpa_hdr->element_id = WPA_ELEMENT;
00151         memcpy(&wpa_hdr->oui, WPA_OUI, sizeof(WPA_OUI));
00152         wpa_hdr->oui_type = 1;
00153 
00154         wpa_hdr->version = WPA_VERSION;
00155         hdr_p = (guint8*)(wpa_hdr + 1);
00156 
00157         /* Group cipher suite */
00158         switch (wlan_status->group_cipher) {
00159         case CIPHER_SUITE_TKIP:
00160                 memcpy(hdr_p, WPA_CIPHER_SUITE_TKIP, CIPHER_SUITE_LEN);
00161                 break;
00162         case CIPHER_SUITE_CCMP:
00163                 memcpy(hdr_p, WPA_CIPHER_SUITE_CCMP, CIPHER_SUITE_LEN);
00164                 break;
00165         case CIPHER_SUITE_WEP104:
00166                 memcpy(hdr_p, WPA_CIPHER_SUITE_WEP104, CIPHER_SUITE_LEN);
00167                 break;
00168         case CIPHER_SUITE_WEP40:
00169                 memcpy(hdr_p, WPA_CIPHER_SUITE_WEP40, CIPHER_SUITE_LEN);
00170                 break;
00171         default:
00172                 DLOG_ERR("Unsupported group cipher suite");
00173                 g_free(wpa_ie);
00174                 return -1;
00175         }
00176 
00177         hdr_p += CIPHER_SUITE_LEN;
00178 
00179         /* Pairwise count */
00180         *hdr_p++ = 1;
00181         *hdr_p++ = 0;
00182 
00183         switch (wlan_status->pairwise_cipher) {
00184         case CIPHER_SUITE_TKIP:
00185                 memcpy(hdr_p, WPA_CIPHER_SUITE_TKIP, CIPHER_SUITE_LEN);
00186                 break;
00187         case CIPHER_SUITE_CCMP:
00188                 memcpy(hdr_p, WPA_CIPHER_SUITE_CCMP, CIPHER_SUITE_LEN); 
00189                 break;
00190         case CIPHER_SUITE_WEP104:
00191                 memcpy(hdr_p, WPA_CIPHER_SUITE_WEP104, CIPHER_SUITE_LEN);
00192                 break;
00193         case CIPHER_SUITE_WEP40:
00194                 memcpy(hdr_p, WPA_CIPHER_SUITE_WEP40, CIPHER_SUITE_LEN);
00195                 break;
00196         default:
00197                 DLOG_ERR("Unsupported pairwise cipher suite");
00198                 g_free(wpa_ie);
00199                 return -1;
00200         }
00201 
00202         hdr_p += CIPHER_SUITE_LEN;
00203 
00204         /* Authentication count */
00205         *hdr_p++ = 1;
00206         *hdr_p++ = 0;
00207 
00208         if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_PSK) {
00209                 DLOG_DEBUG("WPA PSK selected");
00210                 memcpy(hdr_p, WPA_KEY_MGMT_PSK, CIPHER_SUITE_LEN);
00211         } else if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) ==
00212                    WLANCOND_WPA_EAP) {
00213                 DLOG_DEBUG("WPA EAP selected");
00214                 memcpy(hdr_p, WPA_KEY_MGMT_802_1X, CIPHER_SUITE_LEN);
00215         } else {
00216                 DLOG_ERR("Unknown key management suite");
00217                 g_free(wpa_ie);
00218                 return 1;
00219         }
00220 
00221         hdr_p += CIPHER_SUITE_LEN;
00222 
00223         /* Capabilities are empty */
00224 
00225         wpa_hdr->length = (hdr_p - wpa_ie) - 2;
00226 
00227 #ifdef DEBUG_IE
00228         int i;
00229         printf("Own WPA IE:\n");
00230         for (i=0;i<wpa_hdr->length;i++) {
00231                 printf("0x%02x ", wpa_ie[i]);
00232         }
00233         printf("\n");
00234 #endif
00235 
00236         update_own_ie(wpa_ie, wpa_hdr->length + 2);
00237 
00238         return 0;
00239 }
00246 static int generate_wpa2_ie(guint32 encryption,
00247                 struct wlan_status_t *wlan_status)
00248 {
00249 
00250         guint8 *wpa_ie;
00251         struct rsn_ie_t *wpa_hdr;
00252         guint8* hdr_p;
00253 
00254         /* Update the length if you change something */
00255         wpa_ie = g_malloc(sizeof(struct rsn_ie_t)+8+CIPHER_SUITE_LEN*3+
00256                         WLANCOND_PMKID_LEN);
00257 
00258         wpa_hdr = (struct rsn_ie_t*) wpa_ie;
00259         wpa_hdr->element_id = RSN_ELEMENT;
00260 
00261         wpa_hdr->version = RSN_VERSION;
00262         hdr_p = (guint8*)(wpa_hdr + 1);
00263 
00264         /* Group cipher suite */
00265         switch (wlan_status->group_cipher) {
00266         case CIPHER_SUITE_TKIP:
00267                 memcpy(hdr_p, RSN_CIPHER_SUITE_TKIP, CIPHER_SUITE_LEN);
00268                 break;
00269         case CIPHER_SUITE_CCMP:
00270                 memcpy(hdr_p, RSN_CIPHER_SUITE_CCMP, CIPHER_SUITE_LEN);
00271                 break;
00272         case CIPHER_SUITE_WEP104:
00273                 memcpy(hdr_p, RSN_CIPHER_SUITE_WEP104, CIPHER_SUITE_LEN);
00274                 break;
00275         case CIPHER_SUITE_WEP40:
00276                 memcpy(hdr_p, RSN_CIPHER_SUITE_WEP40, CIPHER_SUITE_LEN);
00277                 break;
00278         default:
00279                 DLOG_ERR("Unsupported group cipher suite");
00280                 g_free(wpa_ie);
00281                 return -1;
00282         }
00283 
00284         hdr_p += CIPHER_SUITE_LEN;
00285 
00286         /* Pairwise count */
00287         *hdr_p++ = 1;
00288         *hdr_p++ = 0;
00289 
00290         switch (wlan_status->pairwise_cipher) {
00291         case CIPHER_SUITE_TKIP:
00292                 memcpy(hdr_p, RSN_CIPHER_SUITE_TKIP, CIPHER_SUITE_LEN);
00293                 break;
00294         case CIPHER_SUITE_CCMP:
00295                 memcpy(hdr_p, RSN_CIPHER_SUITE_CCMP, CIPHER_SUITE_LEN); 
00296                 break;
00297         case CIPHER_SUITE_WEP104:
00298                 memcpy(hdr_p, RSN_CIPHER_SUITE_WEP104, CIPHER_SUITE_LEN);
00299                 break;
00300         case CIPHER_SUITE_WEP40:
00301                 memcpy(hdr_p, RSN_CIPHER_SUITE_WEP40, CIPHER_SUITE_LEN);
00302                 break;
00303         default:
00304                 DLOG_ERR("Unsupported pairwise cipher suite");
00305                 g_free(wpa_ie);
00306                 return -1;
00307         }
00308 
00309         hdr_p += CIPHER_SUITE_LEN;
00310 
00311         /* Authentication count */
00312         *hdr_p++ = 1;
00313         *hdr_p++ = 0;
00314 
00315         if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_PSK) {
00316                 memcpy(hdr_p, RSN_KEY_MGMT_PSK, CIPHER_SUITE_LEN);
00317         } else if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) ==
00318                    WLANCOND_WPA_EAP){
00319                 memcpy(hdr_p, RSN_KEY_MGMT_802_1X, CIPHER_SUITE_LEN);
00320         } else {
00321                 DLOG_ERR("Unknown key management suite");
00322                 g_free(wpa_ie);
00323                 return -1;
00324         }
00325 
00326         hdr_p += CIPHER_SUITE_LEN;
00327 
00328         /* Capabilities are empty */
00329         *hdr_p++ = 0;
00330         *hdr_p++ = 0;
00331 
00332         /* PMKID */
00333         unsigned char *pmkid;
00334 
00335         if (find_pmkid_from_pmk_cache(wlan_status->conn.bssid, &pmkid)) {
00336                 DLOG_ERR("Error trying to retrieve the pmkid.");
00337                 g_free(wpa_ie);
00338                 return ESUPPLICANT;
00339         }
00340 
00341         if (pmkid != NULL) {
00342                 *hdr_p++ = 1;
00343                 *hdr_p++ = 0;
00344                 memcpy(hdr_p, pmkid, WLANCOND_PMKID_LEN);
00345                 hdr_p += WLANCOND_PMKID_LEN;
00346         }
00347 
00348         wpa_hdr->length = (hdr_p - wpa_ie) - 2;
00349 
00350 #ifdef DEBUG_IE
00351         int i;
00352         printf("Own WPA IE:\n");
00353         for (i=0;i<wpa_hdr->length;i++) {
00354                 printf("0x%02x ", wpa_ie[i]);
00355         }
00356         printf("\n");
00357 #endif
00358 
00359         update_own_ie(wpa_ie, wpa_hdr->length + 2);
00360 
00361         return 0;
00362 }
00363 
00364 static gint compare_bssid(gconstpointer a, gconstpointer b)
00365 {
00366         return memcmp(a, b, ETH_ALEN);
00367 }
00368 
00373 static void remove_ap_from_black_list(unsigned char* bssid)
00374 {
00375         GSList *list;
00376 
00377         list = g_slist_find_custom(ap_black_list, bssid, &compare_bssid);
00378 
00379         if (list != NULL) {
00380                 unsigned char* bssid_entry = list->data;
00381                 print_mac(WLANCOND_PRIO_MEDIUM,
00382                           "Found black list entry to be removed:",
00383                           bssid);
00384 
00385                 /* Remove the old entry */
00386                 ap_black_list = g_slist_remove(ap_black_list,
00387                                                bssid_entry);
00388                 g_free(bssid_entry);
00389         }
00390 }
00391 
00397 static gboolean mic_failure_timer_cb(void* data)
00398 {
00399         /* Since we get into this function no MIC failure
00400            has happened within last 60 seconds.
00401          */
00402         mic_failure_timer_id = 0;
00403 
00404         print_mac(WLANCOND_PRIO_MEDIUM,
00405                   "No MIC failures within the last 60 seconds for:",
00406                   data);
00407 
00408         remove_ap_from_black_list(data);
00409 
00410         return FALSE;
00411 }
00412 
00418 gboolean is_ap_in_black_list(unsigned char* bssid)
00419 {
00420         GSList *list;
00421 
00422         list = g_slist_find_custom(ap_black_list, bssid, &compare_bssid);
00423 
00424         if (list != NULL) {
00425                 print_mac(WLANCOND_PRIO_HIGH,
00426                           "Found AP from black list:", bssid);
00427                 return TRUE;
00428         }
00429         return FALSE;
00430 }
00431 
00437 static gboolean mic_failure_running_cb(void* data)
00438 {
00439         mic_failure_running_timer_id = 0;
00440 
00441         print_mac(WLANCOND_PRIO_HIGH, "MIC failures off for:", data);
00442 
00443         remove_ap_from_black_list(data);
00444 
00445         return FALSE;
00446 }
00447 
00448 static void add_ap_to_black_list(unsigned char* bssid)
00449 {
00450         ap_black_list = g_slist_prepend(ap_black_list,
00451                         g_memdup(bssid, ETH_ALEN));
00452 }
00453 
00454 static void mic_destroy_cb(gpointer data)
00455 {
00456         //print_mac("Destroying mac:", data);
00457         g_free(data);
00458 }
00459 
00465 int handle_mic_failure(gboolean key_type, unsigned char* bssid)
00466 {
00467 
00468         if (mic_failure_timer_id != 0) {
00469 
00470                 g_source_remove(mic_failure_timer_id);
00471                 mic_failure_timer_id = 0;
00472 
00473                 /* Second failure in 60 seconds, fatal */
00474                 wpa_mic_failure_event(key_type, TRUE);
00475 
00476                 print_mac(WLANCOND_PRIO_HIGH,
00477                           "Second MIC failure, disconnecting AP:", bssid);
00478 
00479                 mlme_command(bssid, WLANCOND_MLME_DEAUTH,
00480                                 WLANCOND_REASON_MIC_FAILURE);
00481 
00482                 set_wlan_state(WLAN_NOT_INITIALIZED,
00483                                 DISCONNECTED_SIGNAL,
00484                                 FALSE);
00485 
00486                 /* Set timer to remember this fatal error for 60 seconds */
00487                 mic_failure_running_timer_id = g_timeout_add_seconds_full(
00488                                 G_PRIORITY_DEFAULT,
00489                                 MIC_FAILURE_TIMEOUT,
00490                                 mic_failure_running_cb,
00491                                 g_memdup(bssid, ETH_ALEN),
00492                                 mic_destroy_cb);
00493 
00494                 add_ap_to_black_list(bssid);
00495 
00496                 return 0;
00497         }
00498 
00499         wpa_mic_failure_event(key_type, FALSE);
00500 
00501         mic_failure_timer_id = g_timeout_add_seconds_full(
00502                         G_PRIORITY_DEFAULT,
00503                         MIC_FAILURE_TIMEOUT,
00504                         mic_failure_timer_cb,
00505                         g_memdup(bssid, ETH_ALEN),
00506                         mic_destroy_cb);
00507 
00508         return 0;
00509 }
00510 
00518 int parse_rsn_ie(unsigned char* wpa_ie, unsigned int wpa_ie_len,
00519                 struct ap_info_t* ap_info)
00520 {
00521         struct rsn_ie_t *wpa_hdr;
00522         guint8 *hdr_p;
00523         guint ind;
00524         guint i;
00525         guint cipher_count = 0;
00526 
00527         /* Do data checking, we have to make sure all the time that we
00528            don't go past the IE length , index variable counts the
00529            remaining data, the spec says that all data after the version
00530            field is optional */
00531 
00532         wpa_hdr = (struct rsn_ie_t*) wpa_ie;
00533 
00534         if (wpa_ie_len < sizeof(struct rsn_ie_t)) {
00535                 DLOG_ERR("WPA IE too short");
00536                 return -1;
00537         }
00538 
00539         if (wpa_hdr->element_id != RSN_ELEMENT) {
00540                 DLOG_ERR("Unknown WPA IE received");
00541                 return -1;
00542         }
00543 
00544         ind = wpa_ie_len - sizeof(*wpa_hdr);
00545         hdr_p = (guint8*)(wpa_hdr + 1);
00546 
00547         if (ind >= CIPHER_SUITE_LEN) {
00548                 ap_info->group_cipher = parse_rsn_cipher_suite(hdr_p);
00549                 hdr_p += CIPHER_SUITE_LEN;
00550                 ind -= CIPHER_SUITE_LEN;
00551         } else {
00552                 DLOG_ERR("Strange length in WPA IE");
00553                 return -1;
00554         }
00555 
00556         if (ind >= 2) {
00557                 ap_info->pairwise_cipher = 0;
00558                 cipher_count = *(guint16*)hdr_p;
00559 
00560                 ind -= 2;
00561 
00562                 if (cipher_count == 0) {
00563                         DLOG_ERR("No pairwise ciphers");
00564                         // Return 0 instead or an error
00565                         return 0;
00566                 }
00567 
00568                 if (ind < cipher_count * CIPHER_SUITE_LEN) {
00569                         DLOG_ERR("Invalid pairwise cipher length");
00570                         return -1;
00571                 }
00572 
00573                 hdr_p += 2;
00574 
00575                 for (i = 0; i < cipher_count; i++) {
00576                         ap_info->pairwise_cipher |= parse_rsn_cipher_suite(hdr_p);
00577                         ind -= CIPHER_SUITE_LEN;
00578                         hdr_p += CIPHER_SUITE_LEN;
00579                 }
00580         } else if (ind == 1) {
00581                 DLOG_ERR("Remaining data too short");
00582                 return -1;
00583         }
00584 
00585         if (ind >= 2) {
00586                 ap_info->key_mgmt = 0;
00587                 cipher_count = *(guint16*)hdr_p;
00588                 hdr_p += 2;
00589                 ind -= 2;
00590 
00591                 if (cipher_count == 0 || ind < cipher_count *
00592                     CIPHER_SUITE_LEN) {
00593                         DLOG_ERR("Invalid key mgmt cipher count or length");
00594                         return -1;
00595                 }
00596 
00597                 for (i = 0; i < cipher_count; i++) {
00598                         ap_info->key_mgmt |= parse_rsn_key_mgmt_suite(hdr_p);
00599                         ind -= CIPHER_SUITE_LEN;
00600                         hdr_p += CIPHER_SUITE_LEN;
00601                 }
00602         } else if (ind == 1) {
00603                 DLOG_ERR("Remaining data too short");
00604                 return -1;
00605         }
00606 
00607         if (ind >= 2) {
00608                 //ap_info->rsn_capabilities = *(guint16*)hdr_p;
00609                 hdr_p += 2;
00610                 ind -= 2;
00611         }
00612 
00613         if (ind > 0) {
00614                 DLOG_DEBUG("IE includes PMKID data");
00615         }
00616         return 0;
00617 }
00618 
00619 
00627 int parse_wpa_ie(unsigned char* wpa_ie, unsigned int wpa_ie_len,
00628                 struct ap_info_t* ap_info)
00629 {
00630         struct wpa_ie_t *wpa_hdr;
00631         guint8 *hdr_p;
00632         guint ind, i;
00633         guint cipher_count = 0;
00634         const guint8 WPA1_OUI[] = { 0x00, 0x50, 0xf2, 1 };
00635 
00636         /* Do data checking, we have to make sure all the time that we
00637            don't go past the IE length , index variable counts the
00638            remaining data, the spec says that all data after the version
00639            field is optional */
00640 
00641         wpa_hdr = (struct wpa_ie_t*) wpa_ie;
00642 
00643         if (wpa_ie_len < sizeof(struct wpa_ie_t)) {
00644                 DLOG_ERR("WPA IE too short");
00645                 return -1;
00646         }
00647 
00648         if (wpa_hdr->element_id != WPA_ELEMENT) {
00649                 DLOG_ERR("Unknown WPA IE received");
00650                 return -1;
00651         }
00652 
00653         if (memcmp(&wpa_hdr->oui, WPA1_OUI, CIPHER_SUITE_LEN) != 0) {
00654                 DLOG_ERR("Invalid WPA header");
00655                 return -1;
00656         }
00657 
00658         ind = wpa_ie_len - sizeof(*wpa_hdr);
00659         hdr_p = (guint8*)(wpa_hdr + 1);
00660 
00661         if (ind >= CIPHER_SUITE_LEN) {
00662                 ap_info->group_cipher = parse_wpa_cipher_suite(hdr_p);
00663                 ind -= CIPHER_SUITE_LEN;
00664                 hdr_p += CIPHER_SUITE_LEN;
00665         } else {
00666                 DLOG_ERR("Strange length in WPA IE");
00667                 return -1;
00668         }
00669 
00670         if (ind >= 2) {
00671                 ap_info->pairwise_cipher = 0;
00672                 cipher_count = *(guint16*)hdr_p;
00673                 ind -= 2;
00674 
00675                 if (cipher_count == 0) {
00676                         DLOG_ERR("No pairwise ciphers");
00677                         // Return 0 instead or an error
00678                         return 0;
00679                 }
00680 
00681                 if (ind < cipher_count * CIPHER_SUITE_LEN) {
00682                         DLOG_ERR("Invalid pairwise cipher length");
00683                         return -1;
00684                 }
00685 
00686                 hdr_p += 2;
00687 
00688                 for (i = 0; i < cipher_count; i++) {
00689                         ap_info->pairwise_cipher |=
00690                                 parse_wpa_cipher_suite(hdr_p);
00691                         ind -= CIPHER_SUITE_LEN;
00692                         hdr_p += CIPHER_SUITE_LEN;
00693                 }
00694         } else if (ind == 1) {
00695                 DLOG_ERR("Remaining data too short");
00696                 return -1;
00697         }
00698 
00699         if (ind >= 2) {
00700                 ap_info->key_mgmt = 0;
00701                 cipher_count = *(guint16*)hdr_p;
00702                 hdr_p += 2;
00703                 ind -= 2;
00704 
00705                 if (cipher_count == 0 || ind < cipher_count *
00706                     CIPHER_SUITE_LEN) {
00707                         DLOG_ERR("Invalid key mgmt cipher count (%d) or length",
00708                                  cipher_count);
00709                         return -1;
00710                 }
00711                 
00712                 for (i = 0; i < cipher_count; i++) {
00713                         ap_info->key_mgmt |= parse_wpa_key_mgmt_suite(hdr_p);
00714                         ind -= CIPHER_SUITE_LEN;
00715                         hdr_p += CIPHER_SUITE_LEN;
00716                 }
00717         } else if (ind == 1) {
00718                 DLOG_ERR("Remaining data too short");
00719                 return -1;
00720         }
00721 
00722         if (ind >= 2) {
00723                 //ap_info->rsn_capabilities = *(guint16*)hdr_p;
00724                 hdr_p += 2;
00725                 ind -= 2;
00726         }
00727 
00728         if (ind > 0) {
00729                 DLOG_ERR("IE too long?");
00730                 return -1;
00731         }
00732         return 0;
00733 }
00734 
00735 gint nl80211_encryption_method(guint32 encryption,
00736                            struct wlan_status_t *wlan_status)
00737 {
00738         gint32 value = 0;
00739         guint32 key_mgmt = 0;
00740         gboolean wpa2 = FALSE;
00741         guint32 authentication = wlan_status->conn.authentication_type;
00742 
00743         if (encryption & WLANCOND_ENCRYPT_WPA2_MASK)
00744                 wpa2 = TRUE;
00745 
00746         if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_PSK) {
00747                 if (wpa2 == TRUE)
00748                         value = WLANCOND_AUTH_WPA_VERSION_WPA2;
00749                 else
00750                         value = WLANCOND_AUTH_WPA_VERSION_WPA;
00751                 key_mgmt = WLANCOND_AUTH_KEY_MGMT_PSK;
00752 
00753         } else if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) ==
00754                         WLANCOND_WPA_EAP) {
00755                 if (wpa2 == TRUE)
00756                         value = WLANCOND_AUTH_WPA_VERSION_WPA2;
00757                 else
00758                         value = WLANCOND_AUTH_WPA_VERSION_WPA;
00759                 key_mgmt = WLANCOND_AUTH_KEY_MGMT_802_1X;
00760         } else {
00761                 value = WLANCOND_AUTH_WPA_VERSION_DISABLED;
00762         }
00763 
00764         if (key_mgmt != 0) {
00765                 // Set Information Element if not WPS mode
00766                 if (authentication != EAP_AUTH_TYPE_WFA_SC) {
00767                         if (wpa2 == TRUE)
00768                                 value = generate_wpa2_ie(encryption,
00769                                                 wlan_status);
00770                         else
00771                                 value = generate_wpa_ie(encryption,
00772                                                 wlan_status);
00773                 }
00774         }
00775 
00776         if (value < 0)
00777                 return value;
00778 
00779         return 0;
00780 }
00781 

Generated on Wed Aug 10 2011 16:02:33 for WLAN Connection Daemon by  doxygen 1.7.1