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

wapi.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 
00041 #include <dbus/dbus.h>
00042 #include <eap-dbus.h>
00043 #include <wlancond.h>
00044 #include "wpa.h"
00045 #include "wapi.h"
00046 #include "common.h"
00047 #include "dbus-handler.h"
00048 #include "log.h"
00049 
00050 #define COUNT_LE(p,s) *p++ = (unsigned char)(s & 0x00ff); *p++ = (unsigned char)((s & 0xff00) >> 8); 
00051 
00057 static guint parse_wapi_key_mgmt_suite(guint8 *suite)
00058 {
00059         if (memcmp(suite, WAPI_KEY_MGMT_CERT, CIPHER_SUITE_LEN) == 0)
00060                 return WLANCOND_WAPI_CERT;
00061         if (memcmp(suite, WAPI_KEY_MGMT_PSK, CIPHER_SUITE_LEN) == 0)
00062                 return WLANCOND_WAPI_PSK;
00063 
00064         return 0;
00065 }
00066 
00073 static guint parse_wapi_cipher_suite(guint8 *suite)
00074 {
00075         if (memcmp(suite, CIPHER_SUITE_WAPI, CIPHER_SUITE_LEN) == 0)
00076                 return CIPHER_SUITE_SMS4;
00077 
00078         return 0;
00079 }
00080 
00087 int generate_wapi_ie(guint32 encryption, struct wlan_status_t *wlan_status)
00088 {
00089         guint8 *wapi_ie;
00090         struct wapi_ie_t *wapi_hdr;
00091         guint8* hdr_p;
00092 
00093         /* Update the length if you change something */
00094         wapi_ie = g_malloc(sizeof(struct wapi_ie_t)+8+CIPHER_SUITE_LEN*3+WLANCOND_PMKID_LEN);
00095         
00096         wapi_hdr = (struct wapi_ie_t*) wapi_ie;
00097         wapi_hdr->element_id = WAPI_ELEMENT;
00098 
00099         wapi_hdr->version = WAPI_VERSION;
00100         hdr_p = (guint8*)(wapi_hdr + 1);
00101 
00102         /* AKM count */
00103         COUNT_LE(hdr_p, 1);
00104 
00105         /* AKM suite */
00106         if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WAPI_PSK) {
00107                 memcpy(hdr_p, WAPI_KEY_MGMT_PSK, CIPHER_SUITE_LEN);
00108         } else if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WAPI_CERT){
00109                 memcpy(hdr_p, WAPI_KEY_MGMT_CERT, CIPHER_SUITE_LEN);
00110         } else {
00111                 DLOG_ERR("Unknown key management suite");
00112                 g_free(wapi_ie);
00113                 return -1;
00114         }
00115 
00116         hdr_p += CIPHER_SUITE_LEN;
00117 
00118         /* Unicast count */
00119         COUNT_LE(hdr_p, 1);
00120 
00121         /* Unicast suite */
00122         if (wlan_status->pairwise_cipher == CIPHER_SUITE_SMS4) {
00123                 memcpy(hdr_p, CIPHER_SUITE_WAPI, CIPHER_SUITE_LEN);
00124         } else {
00125                 DLOG_ERR("Unsupported pairwise cipher suite");
00126                 g_free(wapi_ie);
00127                 return -1;
00128         }
00129         
00130         hdr_p += CIPHER_SUITE_LEN;
00131 
00132         /* Multicast cipher suite */
00133         if (wlan_status->group_cipher == CIPHER_SUITE_SMS4) {
00134                 memcpy(hdr_p, CIPHER_SUITE_WAPI, CIPHER_SUITE_LEN);
00135         } else {
00136                 DLOG_ERR("Unsupported group cipher suite");
00137                 g_free(wapi_ie);
00138                 return -1;
00139         }
00140 
00141         hdr_p += CIPHER_SUITE_LEN;
00142 
00143         /* Capabilities are empty */
00144         
00145         COUNT_LE(hdr_p, 0);
00146 
00147         /* BKID count and BKID */
00148 
00149          unsigned char *bkid;
00150 
00151         /* find_pmkid_from_pmk_cache can be used 
00152            due to similar structure */
00153 
00154         if (find_pmkid_from_pmk_cache(wlan_status->conn.bssid, &bkid)) {
00155                 DLOG_ERR("Error trying to retrieve the bkid.");
00156                 return -1;
00157         }
00158         
00159         if (bkid != NULL) {
00160                 COUNT_LE(hdr_p, 1);
00161                 memcpy(hdr_p, bkid, WLANCOND_PMKID_LEN);
00162                 hdr_p += WLANCOND_PMKID_LEN;
00163         }
00164 
00165         /* 2 is subtracted from length since 
00166            element ID and length are excluded */        
00167         wapi_hdr->length = (hdr_p - wapi_ie) - 2;
00168         
00169 #ifdef DEBUG_IE
00170         int i;
00171         printf("Own WPA IE:\n");
00172         for (i=0;i<wapi_hdr->length;i++) {
00173                 printf("0x%02x ", i,wapi_ie[i]);
00174         }
00175         printf("\n");
00176 #endif
00177 
00178         update_own_ie(wapi_ie, wapi_hdr->length + 2);
00179 
00180         return 0;
00181 }
00182 
00190 int parse_wapi_ie(unsigned char* wapi_ie, unsigned int wapi_ie_len,
00191                 struct ap_info_t* ap_info)
00192 {
00193         struct wapi_ie_t *wapi_hdr;
00194         guint8 *hdr_p;
00195         guint ind;
00196         guint i;
00197         guint cipher_count = 0;
00198 
00199         /* Do data checking, we have to make sure all the time that we
00200            don't go past the IE length , index variable counts the
00201            remaining data, the spec says that all data after the version
00202            field is optional */
00203 
00204         wapi_hdr = (struct wapi_ie_t*) wapi_ie;
00205 
00206         if (wapi_ie_len < sizeof(struct wapi_ie_t)) {
00207                 DLOG_ERR("WAPI IE too short");
00208                 return -1;
00209         }
00210 
00211         if (wapi_hdr->element_id != WAPI_ELEMENT) {
00212                 DLOG_ERR("Unknown WAPI IE received");
00213                 return -1;
00214         }
00215 
00216         ind = wapi_ie_len - sizeof(*wapi_hdr);
00217         hdr_p = (guint8*)(wapi_hdr + 1);
00218 
00219         /* AKM */
00220         if (ind >= 2) {
00221                 ap_info->key_mgmt = 0;
00222                 cipher_count = *(guint16*)hdr_p;
00223                 hdr_p += 2;
00224                 ind -= 2;
00225 
00226                 if (cipher_count == 0 || ind < cipher_count *
00227                                 CIPHER_SUITE_LEN) {
00228                         DLOG_ERR("Invalid key mgmt cipher count or length");
00229                         return -1;
00230                 }
00231 
00232                 /* Currently supports only 1 cipher suite */
00233                 for (i = 0; i < cipher_count; i++) {
00234                         ap_info->key_mgmt |= parse_wapi_key_mgmt_suite(hdr_p);
00235                         ind -= CIPHER_SUITE_LEN;
00236                         hdr_p += CIPHER_SUITE_LEN;
00237                 }
00238 
00239         } else if (ind == 1) {
00240                 DLOG_ERR("Remaining data too short");
00241                 return -1;
00242         }
00243 
00244         /* Unicast cipher suite */
00245         if (ind >= 2) {
00246                 ap_info->pairwise_cipher = 0;
00247                 cipher_count = *(guint16*)hdr_p;
00248                 ind -= 2;
00249 
00250                 if (cipher_count == 0) {
00251                         DLOG_ERR("No pairwise ciphers");
00252                         // Return 0 instead of an error
00253                         return 0;
00254                 }
00255 
00256                 if (ind < cipher_count * CIPHER_SUITE_LEN) {
00257                         DLOG_ERR("Invalid pairwise cipher length");
00258                         return -1;
00259                 }
00260 
00261                 hdr_p += 2;
00262 
00263                 for (i = 0; i < cipher_count; i++) {
00264                         ap_info->pairwise_cipher |= parse_wapi_cipher_suite(hdr_p);
00265                         ind -= CIPHER_SUITE_LEN;
00266                         hdr_p += CIPHER_SUITE_LEN;
00267                 }
00268         } else if (ind == 1) {
00269                 DLOG_ERR("Remaining data too short");
00270                 return -1;
00271         }
00272 
00273         /* Multicast cipher suite */
00274 
00275         if (ind >= CIPHER_SUITE_LEN) {
00276                 ap_info->group_cipher = parse_wapi_cipher_suite(hdr_p);
00277                 hdr_p += CIPHER_SUITE_LEN;
00278                 ind -= CIPHER_SUITE_LEN;
00279         } else {
00280                 DLOG_ERR("Strange length in WAPI IE");
00281                 return -1;
00282         }
00283 
00284         /* Capabilities */      
00285         if (ind >= 2) {
00286                 hdr_p += 2;
00287                 ind -= 2;
00288         }
00289 
00290         if (ind > 0) {
00291                 DLOG_DEBUG("IE includes BKID data");
00292         }
00293 
00294         return 0;
00295 }

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