aboutsummaryrefslogtreecommitdiffstats
path: root/airpcap_loader.c
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2006-10-19 00:48:03 +0000
committerGerald Combs <gerald@wireshark.org>2006-10-19 00:48:03 +0000
commit40b845840829a6054050999387e17cca62fb2871 (patch)
treecc940956999215adcac1f9a36376a87ad9212db5 /airpcap_loader.c
parent320840238698806cbabe5568b1cb085a6d80a24e (diff)
Add support for:
- The AirPcap Multi-Channel Aggregator (which is marketspeak for an "any" device) - Merging the 802.11 dissector WEP key list with AirPcap's - Decrypting WEP in the adapter, in Wireshark, or not at all Update the release notes. svn path=/trunk/; revision=19599
Diffstat (limited to 'airpcap_loader.c')
-rw-r--r--airpcap_loader.c931
1 files changed, 919 insertions, 12 deletions
diff --git a/airpcap_loader.c b/airpcap_loader.c
index d65b06904b..93395382ef 100644
--- a/airpcap_loader.c
+++ b/airpcap_loader.c
@@ -39,8 +39,10 @@
#include <pcap.h>
#endif
-#include "capture_ui_utils.h"
+#include <epan/packet.h>
#include <epan/prefs.h>
+#include <epan/prefs-int.h>
+#include "capture_ui_utils.h"
#include "simple_dialog.h"
@@ -90,6 +92,355 @@ airpcap_if_info_t *airpcap_if_selected = NULL;
/* Airpcap current active interface */
airpcap_if_info_t *airpcap_if_active = NULL;
+/* WLAN preferences pointer */
+module_t *wlan_prefs = NULL;
+
+/* Callback used by the load_wlan_keys() routine in order to read a WEP decryption key */
+static guint
+get_wep_key(pref_t *pref, gpointer ud _U_)
+{
+gchar *my_string = NULL;
+keys_cb_data_t* user_data;
+
+decryption_key_t* new_key;
+
+/* Retrieve user data info */
+user_data = (keys_cb_data_t*)ud;
+
+if (g_strncasecmp(pref->name, "wep_key", 7) == 0 && pref->type == PREF_STRING)
+ {
+ my_string = g_strdup(*pref->varp.string);
+
+ if( my_string != NULL)
+ {
+ /* Key is added only if not null ... */
+ if( (g_strcasecmp(my_string,"") != 0) && (wep_key_is_valid(my_string)))
+ {
+ new_key = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
+
+ new_key->key = g_string_new(my_string);
+ g_free(my_string);
+
+ new_key->bits = new_key->key->len * 4;
+
+ new_key->type = AIRPCAP_KEYTYPE_WEP;
+
+ new_key->ssid = NULL;
+
+ user_data->list = g_list_append(user_data->list,new_key);
+ user_data->number_of_keys++;
+ user_data->current_index++;
+ }
+ }
+ }
+return 0;
+}
+
+/* Callback used by the load_wlan_keys() routine in order to read a WPA decryption key */
+static guint
+get_wpa_key(pref_t *pref, gpointer ud _U_)
+{
+return 1;
+}
+
+/* Callback used by the load_wlan_keys() routine in order to read a WPA2 decryption key */
+static guint
+get_wpa2_key(pref_t *pref, gpointer ud _U_)
+{
+return 1;
+}
+
+/* Returs TRUE if the WEP key is valid, false otherwise */
+gboolean
+wep_key_is_valid(char* key)
+{
+GString *new_key_string;
+gint i=0;
+
+if(key == NULL)
+ return FALSE;
+
+new_key_string = g_string_new(key);
+
+if( ((new_key_string->len) > WEP_KEY_MAX_CHAR_SIZE) || ((new_key_string->len) < 2))
+ {
+ g_string_free(new_key_string,FALSE);
+ return FALSE;
+ }
+if((new_key_string->len % 2) != 0)
+ {
+ g_string_free(new_key_string,FALSE);
+ return FALSE;
+ }
+for(i = 0; i < new_key_string->len; i++)
+ {
+ if(!g_ascii_isxdigit(new_key_string->str[i]))
+ {
+ g_string_free(new_key_string,FALSE);
+ return FALSE;
+ }
+ }
+
+g_string_free(new_key_string,FALSE);
+return TRUE;
+}
+
+/* Callback used by the save_wlan_keys() routine in order to write a decryption key */
+static guint
+set_wep_key(pref_t *pref, gpointer ud _U_)
+{
+gchar *my_string = NULL;
+keys_cb_data_t* user_data;
+gint wep_key_number = 0;
+
+/* Retrieve user data info */
+user_data = (keys_cb_data_t*)ud;
+
+if (g_strncasecmp(pref->name, "wep_key", 7) == 0 && pref->type == PREF_STRING)
+ {
+ /* Ok, the pref we're gonna set is a wep_key ... but what number? */
+ sscanf(pref->name,"wep_key%d",&wep_key_number);
+
+ if(user_data->current_index < user_data->number_of_keys)
+ {
+ if(wep_key_number == (user_data->current_index+1))
+ {
+ my_string = g_strdup((char*)g_list_nth_data(user_data->list,user_data->current_index));
+
+ g_free((void *)*pref->varp.string);
+ *pref->varp.string = (void *)g_strdup(my_string);
+
+ g_free(my_string);
+ }
+ }
+ else /* If the number of keys has been reduced somehow, we need to delete all the other keys
+ * (remember that the new ones have been probably overwritten)
+ */
+ {
+ g_free((void *)*pref->varp.string);
+ *pref->varp.string = (void *)g_strdup(""); /* Do not just free memory!!! Put an 'empty' string! */
+ }
+ user_data->current_index++;
+ }
+
+return 0;
+}
+
+/*
+ * Function used to read the Decryption Keys from the preferences and store them
+ * properly into the airpcap adapter.
+ */
+BOOL
+load_wlan_wep_keys(airpcap_if_info_t* info_if)
+{
+keys_cb_data_t* user_data;
+guint i;
+gchar *tmp = NULL;
+
+if(info_if == NULL) return FALSE;
+
+/* Retrieve the wlan preferences */
+wlan_prefs = prefs_find_module("wlan");
+
+/* Allocate a structure used to keep infos between the callbacks */
+user_data = (keys_cb_data_t*)g_malloc(sizeof(keys_cb_data_t));
+
+/* Fill the structure */
+user_data->list = NULL;
+user_data->current_index = 0;
+user_data->number_of_keys= 0; /* Still unknown */
+
+/* Run the callback on each 802.11 preference */
+prefs_pref_foreach(wlan_prefs, get_wep_key, (gpointer)user_data);
+
+/* Now the key list should be filled */
+
+/*
+ * Signal that we've changed things, and run the 802.11 dissector's
+ * callback
+ */
+wlan_prefs->prefs_changed = TRUE;
+
+prefs_apply(wlan_prefs);
+
+write_wlan_wep_keys_to_regitry(info_if,user_data->list);
+
+/* FREE MEMORY */
+/* free the WEP key string */
+for(i=0;i<g_list_length(user_data->list);i++)
+ {
+ g_free(g_list_nth(user_data->list,i)->data);
+ }
+
+/* free the (empty) list */
+g_list_free(user_data->list);
+
+/* free the user_data structure */
+g_free(user_data);
+
+return TRUE;
+}
+
+/*
+ * This function will tell the airpcap driver the key list to use
+ * This will be stored into the registry...
+ */
+BOOL
+write_wlan_wep_keys_to_regitry(airpcap_if_info_t* info_if, GList* key_list)
+{
+UINT i,j;
+GString *new_key;
+gchar s[3];
+PAirpcapKeysCollection KeysCollection;
+ULONG KeysCollectionSize;
+UCHAR KeyByte;
+UINT keys_in_list = 0;
+decryption_key_t* key_item = NULL;
+
+keys_in_list = g_list_length(key_list);
+
+/*
+ * Save the encryption keys, if we have any of them
+ */
+KeysCollectionSize = 0;
+
+/*
+ * Calculate the size of the keys collection
+ */
+KeysCollectionSize = sizeof(AirpcapKeysCollection) + keys_in_list * sizeof(AirpcapKey);
+
+/*
+ * Allocate the collection
+ */
+KeysCollection = (PAirpcapKeysCollection)malloc(KeysCollectionSize);
+if(!KeysCollection)
+{
+ return FALSE;
+}
+
+/*
+ * Populate the key collection
+ */
+KeysCollection->nKeys = keys_in_list;
+
+for(i = 0; i < keys_in_list; i++)
+{
+ KeysCollection->Keys[i].KeyType = AIRPCAP_KEYTYPE_WEP;
+
+ /* Retrieve the Item corresponding to the i-th key */
+ key_item = (decryption_key_t*)g_list_nth_data(key_list,i);
+ new_key = g_string_new(key_item->key->str);
+
+ KeysCollection->Keys[i].KeyLen = new_key->len / 2;
+ memset(&KeysCollection->Keys[i].KeyData, 0, sizeof(KeysCollection->Keys[i].KeyData));
+
+ for(j = 0 ; j < new_key->len; j += 2)
+ {
+ s[0] = new_key->str[j];
+ s[1] = new_key->str[j+1];
+ s[2] = '\0';
+ KeyByte = (UCHAR)strtol(s, NULL, 16);
+ KeysCollection->Keys[i].KeyData[j / 2] = KeyByte;
+ }
+
+ g_string_free(new_key,TRUE);
+}
+
+/*
+ * Free the old adapter key collection!
+ */
+if(info_if->keysCollection != NULL)
+ g_free(info_if->keysCollection);
+
+/*
+ * Set this collection ad the new one
+ */
+info_if->keysCollection = KeysCollection;
+info_if->keysCollectionSize = KeysCollectionSize;
+
+/*
+ * Configuration must be saved
+ */
+info_if->saved = FALSE;
+
+/*
+ * Write down the changes to the registry
+ */
+airpcap_save_selected_if_configuration(info_if);
+
+return TRUE;
+}
+
+/*
+ * Function used to save to the preference file the Decryption Keys.
+ */
+gboolean
+save_wlan_wep_keys(airpcap_if_info_t* info_if)
+{
+GList* key_list = NULL;
+char* tmp_key = NULL;
+guint keys_in_list,i;
+keys_cb_data_t* user_data;
+
+if(info_if == NULL) return FALSE;
+
+/* Retrieve the wlan preferences */
+wlan_prefs = prefs_find_module("wlan");
+
+/* Allocate a structure used to keep infos between the callbacks */
+user_data = (keys_cb_data_t*)g_malloc(sizeof(keys_cb_data_t));
+
+/* Number of keys in key list */
+keys_in_list = (info_if->keysCollectionSize - sizeof(AirpcapKeysCollection))/sizeof(AirpcapKey);
+
+for(i=0; i<keys_in_list; i++)
+{
+/* Only if it is a WEP key... */
+if(info_if->keysCollection->Keys[i].KeyType == AIRPCAP_KEYTYPE_WEP)
+ {
+ tmp_key = airpcap_get_key_string(info_if->keysCollection->Keys[i]);
+ key_list = g_list_append(key_list,g_strdup(tmp_key));
+ g_free(tmp_key);
+ }
+}
+
+/* Now we know the exact number of WEP keys in the list, so store it ... */
+keys_in_list = g_list_length(key_list);
+
+/* Fill the structure */
+user_data->list = key_list;
+user_data->current_index = 0;
+user_data->number_of_keys= keys_in_list;
+
+/* Retrieve the wlan preferences */
+wlan_prefs = prefs_find_module("wlan");
+
+/* Run the callback on each 802.11 preference */
+prefs_pref_foreach(wlan_prefs, set_wep_key, (gpointer)user_data);
+
+/* Signal that we've changed things, and run the 802.11 dissector's
+ * callback */
+wlan_prefs->prefs_changed = TRUE;
+
+/* Apply changes for the specified preference */
+prefs_apply(wlan_prefs);
+
+/* FREE MEMORY */
+/* free the WEP key string */
+for(i=0;i<g_list_length(user_data->list);i++)
+ {
+ g_free(g_list_nth(user_data->list,i)->data);
+ }
+
+/* free the (empty) list */
+g_list_free(user_data->list);
+
+/* free the user_data structure */
+g_free(user_data);
+
+return TRUE;
+}
+
/*
* Get an error message string for a CANT_GET_INTERFACE_LIST error from
* "get_airpcap_interface_list()".
@@ -250,7 +601,7 @@ airpcap_if_set_device_keys(PAirpcapHandle AdapterHandle, PAirpcapKeysCollection
*/
BOOL
airpcap_if_get_device_keys(PAirpcapHandle AdapterHandle, PAirpcapKeysCollection KeysCollection, PUINT PKeysCollectionSize)
-{
+{
return g_PAirpcapGetDeviceKeys(AdapterHandle,KeysCollection,PKeysCollectionSize);
}
@@ -273,7 +624,7 @@ gchar ebuf[AIRPCAP_ERRBUF_SIZE];
if_info->description = g_strdup(description);
if_info->ip_addr = NULL;
if_info->loopback = FALSE;
-
+
/* Probably I have to switch on the leds!!! */
ad = airpcap_if_open(if_info->name, ebuf);
if(ad)
@@ -385,19 +736,13 @@ get_airpcap_interface_list(int *err, char *err_str)
GList *il = NULL;
airpcap_if_info_t *if_info;
int i, n_adapts;
- AirpcapDeviceDescription *devsList, *adListEntry;
-
- if(g_PAirpcapGetDeviceList == NULL) {
- /* Airpcap.dll not available */
- *err = NO_AIRPCAP_INTERFACES_FOUND;
- return NULL;
- }
+ AirpcapDeviceDescription *devsList, *adListEntry;
if(!g_PAirpcapGetDeviceList(&devsList, err_str))
{
- /* No interfaces */
+ /* No interfaces, return il = NULL; */
*err = NO_AIRPCAP_INTERFACES_FOUND;
- return NULL;
+ return il;
}
/*
@@ -530,6 +875,18 @@ if(key.KeyType == AIRPCAP_KEYTYPE_WEP)
g_free(src);
}
}
+else if(key.KeyType == AIRPCAP_KEYTYPE_TKIP)
+ {
+ /* XXX - Add code here */
+ }
+else if(key.KeyType == AIRPCAP_KEYTYPE_CCMP)
+ {
+ /* XXX - Add code here */
+ }
+else
+ {
+ /* XXX - Add code here */
+ }
return dst;
}
@@ -728,6 +1085,556 @@ if(if_info != NULL)
}
/*
+ * DECRYPTION KEYS FUNCTIONS
+ */
+/*
+ * This function is used for DEBUG POURPOSES ONLY!!!
+ */
+void
+print_key_list(GList* key_list)
+{
+gint n,i;
+decryption_key_t* tmp;
+
+n = g_list_length(key_list);
+
+g_print("\n\n********* KEY LIST **********\n\n");
+
+g_print("NUMBER OF KEYS IN LIST : %d\n\n",n);
+
+for(i =0; i < n; i++)
+{
+g_print("[%d] :\n",i+1);
+tmp = (decryption_key_t*)(g_list_nth_data(key_list,i));
+g_print("KEY : %s\n",tmp->key->str);
+
+g_print("BITS: %d\n",tmp->bits);
+
+if(tmp->type == AIRPCAP_KEYTYPE_WEP)
+ g_print("TYPE: %s\n",AIRPCAP_WEP_KEY_STRING);
+else if(tmp->type == AIRPCAP_KEYTYPE_TKIP)
+ g_print("TYPE: %s\n",AIRPCAP_WPA_KEY_STRING);
+else if(tmp->type == AIRPCAP_KEYTYPE_CCMP)
+ g_print("TYPE: %s\n",AIRPCAP_WPA2_KEY_STRING);
+else
+ g_print("TYPE: %s\n","???");
+
+g_print("SSID: %s\n",(tmp->ssid != NULL) ? tmp->ssid->str : "---");
+g_print("\n");
+}
+
+g_print("\n*****************************\n\n");
+}
+
+/*
+ * Retrieves a GList of decryption_key_t structures containing infos about the
+ * keys for the given adapter... returns NULL if no keys are found.
+ */
+GList*
+get_airpcap_device_keys(airpcap_if_info_t* info_if)
+{
+/* tmp vars */
+char* tmp_key = NULL;
+guint i,keys_in_list = 0;
+
+/* real vars*/
+decryption_key_t *new_key = NULL;
+GList *key_list = NULL;
+
+/* Number of keys in key list */
+if(info_if->keysCollectionSize != 0)
+ keys_in_list = (guint)(info_if->keysCollectionSize - sizeof(AirpcapKeysCollection))/sizeof(AirpcapKey);
+else
+ keys_in_list = 0;
+
+for(i=0; i<keys_in_list; i++)
+{
+/* Different things to do depending on the key type */
+if(info_if->keysCollection->Keys[i].KeyType == AIRPCAP_KEYTYPE_WEP)
+ {
+ /* allocate memory for the new key item */
+ new_key = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
+
+ /* fill the fields */
+ /* KEY */
+ tmp_key = airpcap_get_key_string(info_if->keysCollection->Keys[i]);
+ new_key->key = g_string_new(tmp_key);
+ g_free(tmp_key);
+
+ /* BITS */
+ new_key->bits = new_key->key->len *4; /* every char is 4 bits in WEP keys (it is an exadecimal number) */
+
+ /* SSID not used in WEP keys */
+ new_key->ssid = NULL;
+
+ /* TYPE (WEP in this case) */
+ new_key->type = info_if->keysCollection->Keys[i].KeyType;
+
+ /* Append the new element in the list */
+ key_list = g_list_append(key_list,(gpointer)new_key);
+ }
+else if(info_if->keysCollection->Keys[i].KeyType == AIRPCAP_KEYTYPE_TKIP)
+ {
+ /* XXX - Not supported yet */
+ }
+else if(info_if->keysCollection->Keys[i].KeyType == AIRPCAP_KEYTYPE_CCMP)
+ {
+ /* XXX - Not supported yet */
+ }
+}
+
+return key_list;
+}
+
+/*
+ * Returns the list of the decryption keys specified for wireshark, NULL if
+ * no key is found
+ */
+GList*
+get_wireshark_keys()
+{
+keys_cb_data_t* wep_user_data = NULL;
+keys_cb_data_t* wpa_user_data = NULL;
+keys_cb_data_t* wpa2_user_data= NULL;
+
+gchar *tmp = NULL;
+
+GList* final_list = NULL;
+GList* wep_final_list = NULL;
+GList* wpa_final_list = NULL;
+GList* wpa2_final_list = NULL;
+
+/* Retrieve the wlan preferences */
+wlan_prefs = prefs_find_module("wlan");
+
+/* Allocate a structure used to keep infos between the callbacks */
+wep_user_data = (keys_cb_data_t*)g_malloc(sizeof(keys_cb_data_t));
+
+/* Fill the structure */
+wep_user_data->list = NULL;
+wep_user_data->current_index = 0;
+wep_user_data->number_of_keys= 0; /* Still unknown */
+
+/* Run the callback on each 802.11 preference */
+/* XXX - Right now, only WEP keys will be loaded */
+prefs_pref_foreach(wlan_prefs, get_wep_key, (gpointer)wep_user_data);
+prefs_pref_foreach(wlan_prefs, get_wpa_key, (gpointer)wpa_user_data);
+prefs_pref_foreach(wlan_prefs, get_wpa2_key, (gpointer)wpa2_user_data);
+
+/* Copy the list field in the user data structure pointer into the final_list */
+if(wep_user_data != NULL) wep_final_list = wep_user_data->list;
+if(wpa_user_data != NULL) wpa_final_list = wpa_user_data->list;
+if(wpa2_user_data != NULL) wpa2_final_list = wpa2_user_data->list;
+
+/* XXX - Merge the three lists!!!!! */
+final_list = wep_final_list;
+
+/* free the wep_user_data structure */
+g_free(wep_user_data);
+/* free the wpa_user_data structure */
+g_free(wpa_user_data);
+/* free the wpa2_user_data structure */
+g_free(wpa2_user_data);
+
+return final_list;
+}
+
+/*
+ * Merges two lists of keys and return a newly created GList. If a key is
+ * found multiple times, it will just appear once!
+ * list1 and list 2 pointer will have to be freed manually if needed!!!
+ * If the total number of keys exceeeds the maximum number allowed,
+ * exceeding keys will be discarded...
+ */
+GList*
+merge_key_list(GList* list1, GList* list2)
+{
+guint n1=0,n2=0;
+guint i;
+decryption_key_t *dk1=NULL,
+ *dk2=NULL,
+ *new_dk=NULL;
+
+GList* merged_list = NULL;
+
+if( (list1 == NULL) && (list2 == NULL) )
+ return NULL;
+
+if(list1 == NULL)
+ {
+ n1 = 0;
+ n2 = g_list_length(list2);
+
+ for(i=0;i<n2;i++)
+ {
+ new_dk = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
+ dk2 = (decryption_key_t *)g_list_nth_data(list2,i);
+
+ new_dk->bits = dk2->bits;
+ new_dk->type = dk2->type;
+ new_dk->key = g_string_new(dk2->key->str);
+ if(dk2->ssid != NULL)
+ new_dk->ssid = g_string_new(dk2->ssid->str);
+ else
+ new_dk->ssid = NULL;
+
+ /* Check the total length of the merged list */
+ if(g_list_length(merged_list) < MAX_ENCRYPTION_KEYS)
+ merged_list = g_list_append(merged_list,(gpointer)new_dk);
+ }
+ }
+else if(list2 == NULL)
+ {
+ n1 = g_list_length(list1);
+ n2 = 0;
+
+ for(i=0;i<n1;i++)
+ {
+ new_dk = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
+ dk1 = (decryption_key_t*)g_list_nth_data(list1,i);
+
+ new_dk->bits = dk1->bits;
+ new_dk->type = dk1->type;
+ new_dk->key = g_string_new(dk1->key->str);
+ if(dk1->ssid != NULL)
+ new_dk->ssid = g_string_new(dk1->ssid->str);
+ else
+ new_dk->ssid = NULL;
+
+ /* Check the total length of the merged list */
+ if(g_list_length(merged_list) < MAX_ENCRYPTION_KEYS)
+ merged_list = g_list_append(merged_list,(gpointer)new_dk);
+ }
+ }
+else
+ {
+ n1 = g_list_length(list1);
+ n2 = g_list_length(list2);
+
+ /* Copy the whole list1 into merged_list */
+ for(i=0;i<n1;i++)
+ {
+ new_dk = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
+ dk1 = (decryption_key_t *)g_list_nth_data(list1,i);
+
+ new_dk->bits = dk1->bits;
+ new_dk->type = dk1->type;
+ new_dk->key = g_string_new(dk1->key->str);
+
+ if(dk1->ssid != NULL)
+ new_dk->ssid = g_string_new(dk1->ssid->str);
+ else
+ new_dk->ssid = NULL;
+
+ /* Check the total length of the merged list */
+ if(g_list_length(merged_list) < MAX_ENCRYPTION_KEYS)
+ merged_list = g_list_append(merged_list,(gpointer)new_dk);
+ }
+
+ /* Look for keys that are present in list2 but aren't in list1 yet...
+ * Add them to merged_list
+ */
+ for(i=0;i<n2;i++)
+ {
+ dk2 = (decryption_key_t *)g_list_nth_data(list2,i);
+
+ if(!key_is_in_list(dk2,merged_list))
+ {
+ new_dk = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
+
+ new_dk->bits = dk2->bits;
+ new_dk->type = dk2->type;
+ new_dk->key = g_string_new(dk2->key->str);
+ if(dk2->ssid != NULL)
+ new_dk->ssid = g_string_new(dk2->ssid->str);
+ else
+ new_dk->ssid = NULL;
+
+ /* Check the total length of the merged list */
+ if(g_list_length(merged_list) < MAX_ENCRYPTION_KEYS)
+ merged_list = g_list_append(merged_list,(gpointer)new_dk);
+ }
+ }
+ }
+
+return merged_list;
+}
+
+/*
+ * Use this function to free a key list.
+ */
+void
+free_key_list(GList *list)
+{
+guint i,n;
+decryption_key_t *curr_key;
+
+if(list == NULL)
+ return;
+
+n = g_list_length(list);
+
+for(i = 0; i < n; i++)
+{
+curr_key = (decryption_key_t*)g_list_nth_data(list,i);
+
+/* Free all the strings */
+if(curr_key->key != NULL)
+ g_string_free(curr_key->key,TRUE);
+
+if(curr_key->ssid != NULL)
+g_string_free(curr_key->ssid,TRUE);
+
+/* free the decryption_key_t structure*/
+g_free(curr_key);
+curr_key = NULL;
+}
+
+/* Free the list */
+g_list_free(list);
+
+return;
+}
+
+
+/*
+ * If the given key is contained in the list, returns TRUE.
+ * Returns FALSE otherwise.
+ */
+gboolean
+key_is_in_list(decryption_key_t *dk,GList *list)
+{
+guint i,n;
+decryption_key_t* curr_key = NULL;
+gboolean found = FALSE;
+
+if( (list == NULL) || (dk == NULL) )
+ return FALSE;
+
+n = g_list_length(list);
+
+if(n < 1)
+ return FALSE;
+
+for(i = 0; i < n; i++)
+{
+curr_key = (decryption_key_t*)g_list_nth_data(list,i);
+if(keys_are_equals(dk,curr_key))
+ found = TRUE;
+}
+
+return found;
+}
+
+/*
+ * Returns TRUE if keys are equals, FALSE otherwise
+ */
+gboolean
+keys_are_equals(decryption_key_t *k1,decryption_key_t *k2)
+{
+
+if((k1==NULL) || (k2==NULL))
+ return FALSE;
+
+if( g_string_equal(k1->key,k2->key) &&
+ (k1->bits == k2->bits) && /* If the previous is TRUE, this must be TRUE as well */
+ k1->type == k2->type)
+ {
+ /* Check the ssid... if the key type is WEP, the two fields should be NULL */
+ if((k1->ssid == NULL) && (k2->ssid == NULL))
+ return TRUE;
+
+ /* Check if one of them is null and one is not... */
+ if((k1->ssid == NULL) || (k2->ssid == NULL))
+ return FALSE;
+
+ /* If they are not null, they must share the same ssid */
+ return g_string_equal(k1->ssid,k2->ssid);
+ }
+
+/* Some field is not equal ... */
+return FALSE;
+}
+
+/*
+ * Tests if two collection of keys are equal or not, to be considered equals, they have to
+ * contain the same keys in the SAME ORDER! (If both lists are NULL, which means empty will
+ * return TRUE)
+ */
+gboolean
+key_lists_are_equal(GList* list1, GList* list2)
+{
+guint n1=0,n2=0;
+guint i;
+decryption_key_t *dk1=NULL,*dk2=NULL;
+
+n1 = g_list_length(list1);
+n2 = g_list_length(list2);
+
+if(n1 != n2) return FALSE;
+
+for(i=0;i<n1;i++)
+{
+dk1=(decryption_key_t*)g_list_nth_data(list1,i);
+dk2=(decryption_key_t*)g_list_nth_data(list2,i);
+
+if(!g_string_equal(dk1->key,dk2->key)) return FALSE;
+}
+
+return TRUE;
+}
+
+static guint
+test_if_on(pref_t *pref, gpointer ud _U_)
+{
+gboolean *is_on;
+gboolean number;
+
+/* Retrieve user data info */
+is_on = (gboolean*)ud;
+
+
+if (g_strncasecmp(pref->name, "enable_decryption", 17) == 0 && pref->type == PREF_BOOL)
+ {
+ number = *pref->varp.boolp;
+
+ if(number) *is_on = TRUE;
+ else *is_on = FALSE;
+
+ return 1;
+ }
+return 0;
+}
+
+/*
+ * Returns TRUE if the Wireshark decryption is active, false otherwise
+ */
+gboolean
+wireshark_decryption_on()
+{
+gboolean is_on;
+
+/* Retrieve the wlan preferences */
+wlan_prefs = prefs_find_module("wlan");
+
+/* Run the callback on each 802.11 preference */
+prefs_pref_foreach(wlan_prefs, test_if_on, (gpointer)&is_on);
+
+return is_on;
+}
+
+/*
+ * Returns TRUE if the AirPcap decryption is active, false otherwise
+ */
+gboolean
+airpcap_decryption_on()
+{
+gboolean is_on = FALSE;
+
+if(airpcap_if_selected != NULL)
+ {
+ is_on = (gboolean)airpcap_if_selected->DecryptionOn;
+ }
+
+return is_on;
+}
+
+static guint
+set_on_off(pref_t *pref, gpointer ud _U_)
+{
+gboolean *is_on;
+gboolean number;
+
+/* Retrieve user data info */
+is_on = (gboolean*)ud;
+
+if (g_strncasecmp(pref->name, "enable_decryption", 17) == 0 && pref->type == PREF_BOOL)
+ {
+ number = *pref->varp.boolp;
+
+ g_free((void *)*pref->varp.boolp);
+ if(*is_on)
+ *pref->varp.boolp = TRUE;
+ else
+ *pref->varp.boolp = FALSE;
+
+ return 1;
+ }
+return 0;
+}
+
+/*
+ * Enables decryption for Wireshark if on_off is TRUE, disables it otherwise.
+ */
+void
+set_wireshark_decryption(gboolean on_off)
+{
+gboolean is_on;
+
+is_on = on_off;
+
+/* Retrieve the wlan preferences */
+wlan_prefs = prefs_find_module("wlan");
+
+/* Run the callback on each 802.11 preference */
+prefs_pref_foreach(wlan_prefs, set_on_off, (gpointer)&is_on);
+
+/*
+ * Signal that we've changed things, and run the 802.11 dissector's
+ * callback
+ */
+wlan_prefs->prefs_changed = TRUE;
+
+prefs_apply(wlan_prefs);
+}
+
+/*
+ * Enables decryption for all the adapters if on_off is TRUE, disables it otherwise.
+ */
+gboolean
+set_airpcap_decryption(gboolean on_off)
+{
+/* We need to directly access the .ddl functions here... */
+gchar ebuf[AIRPCAP_ERRBUF_SIZE];
+PAirpcapHandle ad;
+
+gboolean success = TRUE;
+
+gint n = 0;
+gint i = 0;
+airpcap_if_info_t* curr_if = NULL;
+
+n = g_list_length(airpcap_if_list);
+
+/* The same kind of settings should be propagated to all the adapters */
+/* Apply this change to all the adapters !!! */
+for(i = 0; i < n; i++)
+ {
+ curr_if = (airpcap_if_info_t*)g_list_nth_data(airpcap_if_list,i);
+
+ if( curr_if != NULL )
+ {
+ ad = airpcap_if_open(get_airpcap_name_from_description(airpcap_if_list,curr_if->description), ebuf);
+ if(ad)
+ {
+ curr_if->DecryptionOn = (gboolean)on_off;
+ airpcap_if_set_decryption_state(ad,curr_if->DecryptionOn);
+ /* Save configuration for the curr_if */
+ if(!airpcap_if_store_cur_config_as_adapter_default(ad))
+ {
+ success = FALSE;
+ }
+ airpcap_if_close(ad);
+ }
+ }
+ }
+
+return success;
+}
+
+
+/* DINAMICALLY LIBRARY LOADER */
+/*
* Used to dinamically load the airpcap library in order link it only when
* it's present on the system
*/