diff options
author | Gerald Combs <gerald@wireshark.org> | 2015-06-11 15:05:44 -0700 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 2015-06-16 03:45:54 +0000 |
commit | ece4b01f218ab4e71233580e199e830b83958c99 (patch) | |
tree | f7503d8f097b6e3f6406dd3f6b0c69bb46b97909 | |
parent | 2a3fa1418544469e7dc6f0e0fddb6eaab507b71a (diff) |
Add the wireless toolbar.
Add the wireless toolbar to the Qt UI.
Start adding AirPcap support to ui/80211_utils. Add FCS validation
routines to ws80211_utils.
Move a bunch of AirPcap routines that require epan from caputils to
ui/gtk. They were required for driver key management, which we'll
leave to the AirPcap Control Panel in the Qt UI.
Move frequency-utils to wsutil.
Change-Id: I44446758046621d183f5c2ba9f6526bf01e084f1
Reviewed-on: https://code.wireshark.org/review/8910
Petri-Dish: Gerald Combs <gerald@wireshark.org>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Gerald Combs <gerald@wireshark.org>
30 files changed, 2512 insertions, 1529 deletions
diff --git a/capchild/capture_sync.h b/capchild/capture_sync.h index ce107239ce..7449d96939 100644 --- a/capchild/capture_sync.h +++ b/capchild/capture_sync.h @@ -32,6 +32,10 @@ #ifndef __CAPTURE_SYNC_H__ #define __CAPTURE_SYNC_H__ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + /** * Start a new capture session. * Create a capture child which is doing the real capture work. @@ -135,4 +139,8 @@ capture_input_closed(capture_session *cap_session, gchar *msg); /* set a callback to be called after fork with the pid of the forked child */ extern void capture_sync_set_fetch_dumpcap_pid_cb(void(*cb)(ws_process_id pid)); -#endif /* capture_sync.h */ +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CAPTURE_SYNC_H__ */ diff --git a/caputils/airpcap_loader.c b/caputils/airpcap_loader.c index 934063f63d..61818ba0f5 100644 --- a/caputils/airpcap_loader.c +++ b/caputils/airpcap_loader.c @@ -35,19 +35,10 @@ #include <pcap.h> #endif -#include <epan/packet.h> -#include <epan/prefs.h> -#include <epan/prefs-int.h> -#include <epan/uat-int.h> -#include <epan/dissectors/packet-ieee80211.h> -#include <epan/crypt/wep-wpadefs.h> #include <epan/crypt/airpdcap_ws.h> #include <epan/strutil.h> -#include <epan/frequency-utils.h> #include <wsutil/file_util.h> - -#include "ui/capture_ui_utils.h" -#include "ui/simple_dialog.h" +#include <wsutil/frequency-utils.h> #include <caputils/airpcap.h> #include <caputils/airpcap_loader.h> @@ -115,9 +106,6 @@ 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; - Dot11Channel *pSupportedChannels; guint numSupportedChannels; @@ -142,560 +130,6 @@ static AirpcapChannelInfo LegacyChannels[] = static guint num_legacy_channels = 14; /* - * 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) -{ - gchar *key_string = NULL; - guint8 key_type = AIRPDCAP_KEY_TYPE_WEP; - keys_cb_data_t* user_data; - uat_t *uat; - guint i; - char* err = NULL; - uat_wep_key_record_t* wep_keys; - decryption_key_t* new_key; - - /* Retrieve user data info */ - user_data = (keys_cb_data_t*)ud; - - if (g_ascii_strcasecmp(pref->name, "wep_key_table") == 0 && pref->type == PREF_UAT) - { - uat = pref->varp.uat; - /* This is just a sanity check. UAT should be loaded */ - if (!uat->loaded) - { - if (!uat_load(uat, &err)) - { - /* XXX - report the error */ - g_free(err); - return 1; - } - } - - for (i = 0, wep_keys = (uat_wep_key_record_t*)*uat->user_ptr; i < *uat->nrows_p; i++, wep_keys++) - { - /* strip out key type if present */ - if (g_ascii_strncasecmp(wep_keys->string, STRING_KEY_TYPE_WEP ":", 4) == 0) { - key_type = AIRPDCAP_KEY_TYPE_WEP; - key_string = (gchar*)wep_keys->string+4; - } - else if (g_ascii_strncasecmp(wep_keys->string, STRING_KEY_TYPE_WPA_PWD ":", 8) == 0) { - key_string = (gchar*)wep_keys->string+8; - key_type = AIRPDCAP_KEY_TYPE_WPA_PWD; - } - else if (g_ascii_strncasecmp(wep_keys->string, STRING_KEY_TYPE_WPA_PSK ":", 8) == 0) { - key_string = (gchar*)wep_keys->string+8; - key_type = AIRPDCAP_KEY_TYPE_WPA_PSK; - } - else { - key_type = wep_keys->key; - key_string = (gchar*)wep_keys->string; - } - - /* Here we have the string describing the key... */ - new_key = parse_key_string(key_string, key_type); - - if (new_key != NULL) - { - /* Key is added only if not null ... */ - user_data->list = g_list_append(user_data->list,new_key); - user_data->number_of_keys++; - user_data->current_index++; - } - } - } - return 0; -} - -/* Returs TRUE if the WEP key is valid, false otherwise */ -gboolean -wep_key_is_valid(char* key) -{ - size_t strsize, i; - - if (key == NULL) - return FALSE; - - strsize = strlen(key); - - if ( (strsize > WEP_KEY_MAX_CHAR_SIZE) || (strsize < 2)) - { - return FALSE; - } - if ((strsize % 2) != 0) - { - return FALSE; - } - for(i = 0; i < strsize; i++) - { - if (!g_ascii_isxdigit(key[i])) - { - return 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_) -{ - keys_cb_data_t* user_data; - uat_t *uat; - gint i; - char* err = NULL; - uat_wep_key_record_t uat_key; - - decryption_key_t* new_key; - - /* Retrieve user data info */ - user_data = (keys_cb_data_t*)ud; - - if (g_ascii_strcasecmp(pref->name, "wep_key_table") == 0 && pref->type == PREF_UAT) - { - uat = pref->varp.uat; - if (!uat->loaded) - { - /* UAT will only be loaded if previous keys exist, so it may need - to be loaded now */ - if (!uat_load(uat, &err)) - { - /* XXX - report the error */ - g_free(err); - return 1; - } - uat->loaded = 1; - } - /* Free the old records */ - uat_clear(uat); - - for (i = 0; i < user_data->number_of_keys; i++) - { - new_key = (decryption_key_t*)g_list_nth_data(user_data->list,i); - - uat_key.string = get_key_string(new_key); - uat_key.key = new_key->type; - uat_add_record(uat, &uat_key, TRUE); - } - - if (!uat_save(uat, &err)) - { - /* XXX - report the error */ - g_free(err); - return 1; - } - } - - return 0; -} - -/* - * Function used to read the Decryption Keys from the preferences and store them - * properly into the airpcap adapter. - */ -gboolean -load_wlan_driver_wep_keys(void) -{ - keys_cb_data_t* user_data; - guint i; - - /* 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_driver_wep_keys_to_registry(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); - - /* airpcap_if_info_free(fake_info_if); */ - - return TRUE; -} - -/* - * This function will tell the airpcap driver the key list to use - * This will be stored into the registry... - */ -gboolean -write_wlan_wep_keys_to_registry(airpcap_if_info_t* info_if, GList* key_list) -{ - guint i,j; - GString *new_key; - gchar s[3]; - PAirpcapKeysCollection KeysCollection; - guint KeysCollectionSize; - guint8 KeyByte; - guint keys_in_list = 0; - decryption_key_t* key_item = NULL; - - keys_in_list = g_list_length(key_list); - - /* - * Calculate the size of the keys collection - */ - KeysCollectionSize = (guint)AirpcapKeysCollectionSize(keys_in_list); - - /* - * Allocate the collection - */ - KeysCollection = (PAirpcapKeysCollection)g_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 = AIRPDCAP_KEY_TYPE_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 = (guint) 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 = (guint8)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; -} - -/* - * This function will tell the airpcap driver the key list to use - * This will be stored into the registry... - */ -gboolean -write_wlan_driver_wep_keys_to_registry(GList* key_list) -{ - guint i,j,k,n,y; - GString *new_key; - gchar s[3]; - PAirpcapKeysCollection KeysCollection; - guint KeysCollectionSize; - guint8 KeyByte; - guint keys_in_list = 0; - decryption_key_t* key_item = NULL; - airpcap_if_info_t* fake_info_if = NULL; - - /* Create the fake_info_if from the first adapter of the list */ - fake_info_if = airpcap_driver_fake_if_info_new(); - - if (fake_info_if == NULL) - return FALSE; - - /* - * XXX - When WPA will be supported, change this to: keys_in_list = g_list_length(key_list); - * but right now we will have to count only the WEP keys (or we will have a malloc-mess :-) ) - */ - n = g_list_length(key_list); - for(k = 0; k < n; k++ ) - if (((decryption_key_t*)g_list_nth_data(key_list,k))->type == AIRPDCAP_KEY_TYPE_WEP) - keys_in_list++; - - /* - * Calculate the size of the keys collection - */ - KeysCollectionSize = (guint)AirpcapKeysCollectionSize(keys_in_list); - - /* - * Allocate the collection - */ - KeysCollection = (PAirpcapKeysCollection)g_malloc(KeysCollectionSize); - if (!KeysCollection) - { - return FALSE; - } - - /* - * Populate the key collection - */ - KeysCollection->nKeys = keys_in_list; - - /* - * XXX - If we have, let's say, six keys, the first three are WEP, then two are WPA, and the - * last is WEP, we have to scroll the whole list (n) but increment the array counter only - * when a WEP key is found (y) .. When WPA will be supported by the driver, I'll have to change - * this - */ - y = 0; /* Current position in the key list */ - - for(i = 0; i < n; i++) - { - /* Retrieve the Item corresponding to the i-th key */ - key_item = (decryption_key_t*)g_list_nth_data(key_list,i); - - /* - * XXX - The AIRPDCAP_KEY_TYPE_WEP is the only supported right now! - * We will have to modify the AirpcapKey structure in order to - * support the other two types! What happens now, is that simply the - * not supported keys will just be discarded (they will be saved in Wireshark though) - */ - if (key_item->type == AIRPDCAP_KEY_TYPE_WEP) - { - KeysCollection->Keys[y].KeyType = AIRPDCAP_KEY_TYPE_WEP; - - new_key = g_string_new(key_item->key->str); - - KeysCollection->Keys[y].KeyLen = (guint) new_key->len / 2; - memset(&KeysCollection->Keys[y].KeyData, 0, sizeof(KeysCollection->Keys[y].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 = (guint8)strtol(s, NULL, 16); - KeysCollection->Keys[y].KeyData[j / 2] = KeyByte; - } - /* XXX - Change when WPA will be supported!!! */ - y++; - g_string_free(new_key,TRUE); - } - else if (key_item->type == AIRPDCAP_KEY_TYPE_WPA_PWD) - { - /* XXX - The driver cannot deal with this kind of key yet... */ - } - else if (key_item->type == AIRPDCAP_KEY_TYPE_WPA_PMK) - { - /* XXX - The driver cannot deal with this kind of key yet... */ - } - } - - /* - * Free the old adapter key collection! - */ - if (fake_info_if->keysCollection != NULL) - g_free(fake_info_if->keysCollection); - - /* - * Set this collection ad the new one - */ - fake_info_if->keysCollection = KeysCollection; - fake_info_if->keysCollectionSize = KeysCollectionSize; - - /* - * Configuration must be saved - */ - fake_info_if->saved = FALSE; - - /* - * Write down the changes to the registry - */ - airpcap_save_driver_if_configuration(fake_info_if); - - airpcap_if_info_free(fake_info_if); - - return TRUE; -} - -/* - * Function used to save to the preference file the Decryption Keys. - */ -int -save_wlan_driver_wep_keys(void) -{ - GList* key_list = NULL; - char* tmp_key = NULL; - guint keys_in_list,i; - keys_cb_data_t* user_data; - airpcap_if_info_t* fake_info_if = NULL; - - /* Create the fake_info_if from the first adapter of the list */ - fake_info_if = airpcap_driver_fake_if_info_new(); - - if (fake_info_if == NULL) - return 0; - - /* 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 */ - if (fake_info_if->keysCollectionSize != 0) - keys_in_list = AirpcapKeysCollectionSizeToKeyCount(fake_info_if->keysCollectionSize); - else - keys_in_list = 0; - - for(i=0; i<keys_in_list; i++) - { - /* Only if it is a WEP key... */ - if (fake_info_if->keysCollection->Keys[i].KeyType == AIRPDCAP_KEY_TYPE_WEP) - { - tmp_key = airpcap_get_key_string(fake_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); - - airpcap_if_info_free(fake_info_if); - - return keys_in_list; -} - -/* - * Function used to save to the preference file the Decryption Keys. - */ -int -save_wlan_wireshark_wep_keys(GList* key_ls) -{ - GList* key_list = NULL; - guint keys_in_list,i; - keys_cb_data_t* user_data; - decryption_key_t* tmp_dk; - - /* 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)); - - keys_in_list = g_list_length(key_ls); - - key_list = key_ls; - - /* 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++) - { - tmp_dk = (decryption_key_t*)g_list_nth(user_data->list,i)->data; - g_string_free(tmp_dk->key,TRUE); - if (tmp_dk->ssid != NULL) g_byte_array_free(tmp_dk->ssid,TRUE); - } - - /* free the (empty) list */ - g_list_free(user_data->list); - - /* free the user_data structure */ - g_free(user_data); - - return keys_in_list; -} - -/* * Get an error message string for a CANT_GET_INTERFACE_LIST error from * "get_airpcap_interface_list()". */ @@ -1207,6 +641,7 @@ airpcap_driver_fake_if_info_new(void) return fake_if_info; } +#ifdef AIRPCAP_DEBUG /* * USED FOR DEBUG ONLY... PRINTS AN AirPcap ADAPTER STRUCTURE in a fancy way. */ @@ -1247,6 +682,7 @@ airpcap_if_info_print(airpcap_if_info_t* if_info) } g_print("\n\n"); } +#endif /* AIRPCAP_DEBUG */ /* * Function used to load the WEP keys for a selected interface @@ -1467,56 +903,12 @@ airpcap_if_info_t* get_airpcap_if_from_name(GList* if_list, const gchar* name) if (if_info && (g_ascii_strcasecmp(if_info->name, name) == 0)) { return (if_info); } - } - return (NULL); -} - -/* - * Returns the ASCII string of a key given the key bytes - */ -gchar* -airpcap_get_key_string(AirpcapKey key) -{ - unsigned int j = 0; - gchar *dst,*src; - - dst = NULL; - src = NULL; - - if (key.KeyType == AIRPDCAP_KEY_TYPE_WEP) - { - if (key.KeyLen != 0) - { - /* Allocate the string used to store the ASCII representation of the WEP key */ - dst = (gchar*)g_malloc(sizeof(gchar)*WEP_KEY_MAX_CHAR_SIZE + 1); - /* Make sure that the first char is '\0' in order to make g_strlcat() work */ - dst[0]='\0'; - - for(j = 0; j < key.KeyLen; j++) - { - src = g_strdup_printf("%.2x", key.KeyData[j]); - /* - * XXX - use g_strconcat() or GStrings instead ??? - */ - g_strlcat(dst, src, WEP_KEY_MAX_CHAR_SIZE+1); - } - g_free(src); + /* Try the name without the "\\.\" prefix. */ + if (strlen(if_info->name) > 4 && (g_ascii_strcasecmp(if_info->name + 4, name) == 0)) { + return (if_info); } } - else if (key.KeyType == AIRPDCAP_KEY_TYPE_WPA_PWD) - { - /* XXX - Add code here */ - } - else if (key.KeyType == AIRPDCAP_KEY_TYPE_WPA_PMK) - { - /* XXX - Add code here */ - } - else - { - /* XXX - Add code here */ - } - - return dst; + return (NULL); } /* @@ -1591,22 +983,6 @@ airpcap_get_if_string_number_from_description(gchar* description) } /* - * Returns the default airpcap interface of a list, NULL if list is empty - */ -airpcap_if_info_t* -airpcap_get_default_if(GList* airpcap_if_list_p) -{ - airpcap_if_info_t* if_info = NULL; - - if ((prefs.capture_device != NULL) && (*prefs.capture_device != '\0')) - { - if_info = get_airpcap_if_from_name(airpcap_if_list_p, - get_if_name(prefs.capture_device)); - } - return if_info; -} - -/* * Load the configuration for the specified interface */ void @@ -1640,10 +1016,12 @@ airpcap_load_selected_if_configuration(airpcap_if_info_t* if_info) if_info->saved = TRUE; } +#if 0 else { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, " Error in opening adapter for %s",if_info->description); } +#endif } } @@ -1680,7 +1058,9 @@ airpcap_save_selected_if_configuration(airpcap_if_info_t* if_info) /* ... and save them */ if (!airpcap_if_store_cur_config_as_adapter_default(ad)) { +#if 0 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Cannot save Wireless configuration!!!\nRemember that in order to store the configuration in the registry you have to:\n\n- Close all the airpcap-based applications.\n- Be sure to have administrative privileges."); +#endif if_info->saved = FALSE; airpcap_if_close(ad); return; @@ -1689,10 +1069,12 @@ airpcap_save_selected_if_configuration(airpcap_if_info_t* if_info) if_info->saved = TRUE; airpcap_if_close(ad); } +#if 0 else { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, " Error in opening adapter for %s",if_info->description); } +#endif } } @@ -1716,580 +1098,18 @@ airpcap_save_driver_if_configuration(airpcap_if_info_t* fake_if_info) airpcap_if_save_driver_keys(ad,fake_if_info); airpcap_if_close(ad); } +#if 0 else { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, " Error in opening adapter for %s",fake_if_info->description); } +#endif } return; } /* - * 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; - - if (key_list == NULL) - { - g_print("\n\n******* KEY LIST NULL *******\n\n"); - return; - } - - 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 == AIRPDCAP_KEY_TYPE_WEP) - g_print("TYPE: %s\n",AIRPCAP_WEP_KEY_STRING); - else if (tmp->type == AIRPDCAP_KEY_TYPE_WPA_PWD) - g_print("TYPE: %s\n",AIRPCAP_WPA_PWD_KEY_STRING); - else if (tmp->type == AIRPDCAP_KEY_TYPE_WPA_PMK) - g_print("TYPE: %s\n",AIRPCAP_WPA_BIN_KEY_STRING); - else - g_print("TYPE: %s\n","???"); - - g_print("SSID: %s\n",(tmp->ssid != NULL) ? - format_text((guchar *)tmp->ssid->data, tmp->ssid->len) : "---"); - 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 = AirpcapKeysCollectionSizeToKeyCount(info_if->keysCollectionSize); - 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 == AIRPDCAP_KEY_TYPE_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 = (guint) new_key->key->len *4; /* every char is 4 bits in WEP keys (it is an hexadecimal 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 == AIRPDCAP_KEY_TYPE_WPA_PWD) - { - /* XXX - Not supported yet */ - } - else if (info_if->keysCollection->Keys[i].KeyType == AIRPDCAP_KEY_TYPE_WPA_PMK) - { - /* XXX - Not supported yet */ - } - } - - return key_list; -} - -/* - * Retrieves a GList of decryption_key_t structures containing infos about the - * keys for the global AirPcap driver... returns NULL if no keys are found. - */ -GList * -get_airpcap_driver_keys(void) -{ - /* tmp vars */ - char *tmp_key = NULL; - guint i,keys_in_list = 0; - - /* real vars*/ - decryption_key_t *new_key = NULL; - GList *key_list = NULL; - - /* - * To read the drivers general settings we need to create and use one airpcap adapter... - * The only way to do that is to instantiate a fake adapter, and then close it and delete it. - */ - airpcap_if_info_t* fake_info_if = NULL; - - /* Create the fake_info_if from the first adapter of the list */ - fake_info_if = airpcap_driver_fake_if_info_new(); - - if (fake_info_if == NULL) - return NULL; - - /* Number of keys in key list */ - if (fake_info_if->keysCollectionSize != 0) - keys_in_list = AirpcapKeysCollectionSizeToKeyCount(fake_info_if->keysCollectionSize); - else - keys_in_list = 0; - - for(i=0; i<keys_in_list; i++) - { - /* Different things to do depending on the key type */ - if (fake_info_if->keysCollection->Keys[i].KeyType == AIRPDCAP_KEY_TYPE_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(fake_info_if->keysCollection->Keys[i]); - new_key->key = g_string_new(tmp_key); - if (tmp_key != NULL) g_free(tmp_key); - - /* BITS */ - new_key->bits = (guint) new_key->key->len *4; /* every char is 4 bits in WEP keys (it is an hexadecimal number) */ - - /* SSID not used in WEP keys */ - new_key->ssid = NULL; - - /* TYPE (WEP in this case) */ - new_key->type = fake_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 (fake_info_if->keysCollection->Keys[i].KeyType == AIRPDCAP_KEY_TYPE_WPA_PWD) - { - /* XXX - Not supported yet */ - } - else if (fake_info_if->keysCollection->Keys[i].KeyType == AIRPDCAP_KEY_TYPE_WPA_PMK) - { - /* XXX - Not supported yet */ - } - } - - airpcap_if_info_free(fake_info_if); - - return key_list; -} - -/* - * Returns the list of the decryption keys specified for wireshark, NULL if - * no key is found - */ -GList * -get_wireshark_keys(void) -{ - keys_cb_data_t *wep_user_data = NULL; - - GList *final_list = NULL; - GList *wep_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); - - /* Copy the list field in the user data structure pointer into the final_list */ - wep_final_list = wep_user_data->list; - - /* XXX - Merge the three lists!!!!! */ - final_list = wep_final_list; - - /* free the wep_user_data structure */ - g_free(wep_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) - { - 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); - new_dk->ssid = byte_array_dup(dk2->ssid); - - /* 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); - - 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); - new_dk->ssid = byte_array_dup(dk1->ssid); - - /* 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); - new_dk->ssid = byte_array_dup(dk1->ssid); - - /* 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); - new_dk->ssid = byte_array_dup(dk2->ssid); - - /* 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_byte_array_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; - - /* XXX - Remove this check when we will have the WPA/WPA2 decryption in the Driver! */ - /** if ( (k1->type == AIRPDCAP_KEY_TYPE_WPA_PWD) || (k2->type == AIRPDCAP_KEY_TYPE_WPA_PWD) || (k1->type == AIRPDCAP_KEY_TYPE_WPA_PMK) || (k2->type == AIRPDCAP_KEY_TYPE_WPA_PMK) ) **/ - /** return TRUE; **/ - - 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; - - /* If they are not null, they must share the same ssid */ - return byte_array_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; - /* XXX - Remove */ - guint wep_n1 = 0,wep_n2=0; - GList *wep_list1 = NULL; - GList *wep_list2 = NULL; - /* XXX - END*/ - guint i/*,j*/; - decryption_key_t *dk1=NULL,*dk2=NULL; - - n1 = g_list_length(list1); - n2 = g_list_length(list2); - - /* - * XXX - START : Retrieve the aublists of WEP keys!!! This is needed only 'till Driver WPA decryption - * is implemented. - */ - for(i=0;i<n1;i++) - { - dk1=(decryption_key_t*)g_list_nth_data(list1,i); - if (dk1->type == AIRPDCAP_KEY_TYPE_WEP) - { - wep_list1 = g_list_append(wep_list1,(gpointer)dk1); - wep_n1++; - } - } - for(i=0;i<n2;i++) - { - dk2=(decryption_key_t*)g_list_nth_data(list2,i); - if (dk2->type == AIRPDCAP_KEY_TYPE_WEP) - { - wep_list2 = g_list_append(wep_list2,(gpointer)dk2); - wep_n2++; - } - } - - /* - * XXX - END : Remove from START to END when the WPA/WPA2 decryption will be implemented in - * the Driver - */ - - /* - * Commented, because in the new AirPcap version all the keys will be saved - * into the driver, and all the keys for every specific adapter will be - * removed. This means that this check will always fail... and the user will - * always be asked what to do... and it doesn't make much sense. - */ - /* if (n1 != n2) return FALSE; */ - if (wep_n1 != wep_n2) return FALSE; - - n2 = wep_n2; - - /*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; - }*/ - for(i=0;i<n2;i++) - { - dk2=(decryption_key_t*)g_list_nth_data(wep_list2,i); - if (!key_is_in_list(dk2,wep_list1)) return FALSE; - } - - return TRUE; -} - -static guint -test_if_on(pref_t *pref, gpointer ud) -{ - gboolean *is_on; - gboolean number; - - /* Retrieve user data info */ - is_on = (gboolean*)ud; - - - if (g_ascii_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 - * XXX - Should we just add a routine to packet-ieee80211.c to grab this directly? - */ -gboolean -wireshark_decryption_on(void) -{ - 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 for the current adapter is active, false otherwise - */ -gboolean -airpcap_decryption_on(void) -{ - gboolean is_on = FALSE; - - airpcap_if_info_t* fake_if_info = NULL; - - fake_if_info = airpcap_driver_fake_if_info_new(); - - if (fake_if_info != NULL) - { - if (fake_if_info->DecryptionOn == AIRPCAP_DECRYPTION_ON) - is_on = TRUE; - else if (fake_if_info->DecryptionOn == AIRPCAP_DECRYPTION_OFF) - is_on = FALSE; - } - - airpcap_if_info_free(fake_if_info); - - return is_on; -} - -/* * Free an instance of airpcap_if_info_t */ void @@ -2323,119 +1143,6 @@ airpcap_if_info_free(airpcap_if_info_t *if_info) } } -static guint -set_on_off(pref_t *pref, gpointer ud) -{ - gboolean *is_on; - - /* Retrieve user data info */ - is_on = (gboolean*)ud; - - if (g_ascii_strncasecmp(pref->name, "enable_decryption", 17) == 0 && pref->type == PREF_BOOL) - { - - 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 .dll functions here... */ - gchar ebuf[AIRPCAP_ERRBUF_SIZE]; - PAirpcapHandle ad,ad_driver; - - gboolean success = TRUE; - - gint n = 0; - gint i = 0; - airpcap_if_info_t* curr_if = NULL; - airpcap_if_info_t* fake_if_info = NULL; - - fake_if_info = airpcap_driver_fake_if_info_new(); - - if (fake_if_info == NULL) - /* We apparently don't have any adapters installed. - * This isn't a failure, so return TRUE - */ - return TRUE; - - /* Set the driver decryption */ - ad_driver = airpcap_if_open(fake_if_info->name, ebuf); - if (ad_driver) - { - if (on_off) - airpcap_if_set_driver_decryption_state(ad_driver,AIRPCAP_DECRYPTION_ON); - else - airpcap_if_set_driver_decryption_state(ad_driver,AIRPCAP_DECRYPTION_OFF); - - airpcap_if_close(ad_driver); - } - - airpcap_if_info_free(fake_if_info); - - n = g_list_length(airpcap_if_list); - - /* Set to FALSE the decryption for 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(curr_if->name, ebuf); - if (ad) - { - curr_if->DecryptionOn = AIRPCAP_DECRYPTION_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; -} - /* DYNAMIC LIBRARY LOADER */ /* diff --git a/caputils/airpcap_loader.h b/caputils/airpcap_loader.h index ef8248f3a5..9eea487b02 100644 --- a/caputils/airpcap_loader.h +++ b/caputils/airpcap_loader.h @@ -51,6 +51,8 @@ extern "C" { #define AIRPCAP_DLL_ERROR 2 #define AIRPCAP_DLL_NOT_FOUND 3 +/* #define AIRPCAP_DEBUG 1 */ + typedef gchar * (*AirpcapGetLastErrorHandler)(PAirpcapHandle AdapterHandle); typedef gboolean (*AirpcapGetDeviceListHandler)(PAirpcapDeviceDescription *PPAllDevs, gchar * Ebuf); typedef void (*AirpcapFreeDeviceListHandler)(PAirpcapDeviceDescription PAllDevs); @@ -141,38 +143,13 @@ extern airpcap_if_info_t *airpcap_if_selected; /* Airpcap current active interface */ extern airpcap_if_info_t *airpcap_if_active; -/* WLAN preferences pointer */ -/*extern module_t *wlan_prefs; - TODO: What is this?? */ - -/* - * Function used to read the Decryption Keys from the preferences and store them - * properly into the airpcap adapter. - */ -gboolean -load_wlan_driver_wep_keys(void); - -/* - * Function used to save to the prefereces file the Decryption Keys. - */ -gboolean -save_wlan_wep_keys(airpcap_if_info_t* info_if); - -/* - * This function will tell the airpcap driver the key list to use - * This will be stored into the registry... - */ -gboolean -write_wlan_wep_keys_to_registry(airpcap_if_info_t* info_if, GList* key_list); - -/* Returs TRUE if the WEP key is valid, false otherwise */ -gboolean -wep_key_is_valid(char* key); - +#ifdef AIRPCAP_DEBUG /* * USED FOR DEBUG ONLY... PRINTS AN AirPcap ADAPTER STRUCTURE in a fancy way. */ void airpcap_if_info_print(airpcap_if_info_t* if_info); +#endif /* * Used to retrieve the two chars string from interface @@ -188,7 +165,7 @@ free_airpcap_interface_list(GList *if_list); /* * Used to retrieve the interface given the name - * (the name is used in AirpcapOpen) + * (the name is used in AirpcapOpen). */ airpcap_if_info_t* get_airpcap_if_from_name(GList* if_list, const gchar* name); @@ -234,6 +211,7 @@ airpcap_if_get_fcs_validation(PAirpcapHandle ah, PAirpcapValidationType val); gboolean airpcap_if_set_fcs_validation(PAirpcapHandle ah, AirpcapValidationType val); +/* Many of these are GTK+ only. */ /* * Airpcap wrapper, used to get the decryption enabling of an airpcap adapter */ @@ -352,14 +330,7 @@ int load_airpcap(void); * This function will use the airpcap.dll to find all the airpcap devices. * Will return null if no device is found. */ -GList* -get_airpcap_interface_list(int *err, char **err_str); - -/* - * Returns the ASCII string of a key given the key bites - */ -gchar* -airpcap_get_key_string(AirpcapKey key); +GList* get_airpcap_interface_list(int *err, char **err_str); /* * Load the configuration for the specified interface @@ -380,12 +351,6 @@ gchar* airpcap_get_if_string_number(airpcap_if_info_t* if_info); /* - * Returns the default airpcap interface of a list, NULL if list is empty - */ -airpcap_if_info_t* -airpcap_get_default_if(GList* airpcap_if_list); - -/* * Airpcap wrapper, used to save the settings for the selected_if */ gboolean @@ -433,118 +398,12 @@ void airpcap_if_info_free(airpcap_if_info_t *if_info); /* - * This function will tell the airpcap driver the key list to use - * This will be stored into the registry... - */ -gboolean -write_wlan_driver_wep_keys_to_registry(GList* key_list); - -/* * Clear keys and decryption status for the specified interface */ void airpcap_if_clear_decryption_settings(airpcap_if_info_t* info_if); /* - * Function used to save to the preference file the Decryption Keys. - */ -int -save_wlan_driver_wep_keys(void); - -/* - * Function used to save to the preference file the Decryption Keys. - */ -int -save_wlan_wireshark_wep_keys(GList* key_ls); - -/* - * DECRYPTION KEYS FUNCTIONS - */ -/* - * This function is used for DEBUG PURPOSES ONLY!!! - */ -void -print_key_list(GList* key_list); - -/* - * 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* if_info); - -/* - * Retrieves a GList of decryption_key_t structures containing infos about the - * keys for the global AirPcap driver... returns NULL if no keys are found. - */ -GList* -get_airpcap_driver_keys(void); - -/* - * Returns the list of the decryption keys specified for wireshark, NULL if - * no key is found - */ -GList* -get_wireshark_keys(void); - -/* - * 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); - -/* - * Merges two lists of keys. If a key is found multiple times, it will just appear once! - */ -GList* -merge_key_list(GList* list1, GList* list2); - -/* - * 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); - -/* - * Returns TRUE if keys are equals, FALSE otherwise - */ -gboolean -keys_are_equals(decryption_key_t *k1,decryption_key_t *k2); - -/* - * Use this function to free a key list. - */ -void -free_key_list(GList *list); - -/* - * Returns TRUE if the Wireshark decryption is active, FALSE otherwise - */ -gboolean -wireshark_decryption_on(void); - -/* - * Returns TRUE if the AirPcap decryption for the current adapter is active, FALSE otherwise - */ -gboolean -airpcap_decryption_on(void); - -/* - * Enables decryption for Wireshark if on_off is TRUE, disables it otherwise. - */ -void -set_wireshark_decryption(gboolean on_off); - -/* - * Enables decryption for all the adapters if on_off is TRUE, disables it otherwise. - */ -gboolean -set_airpcap_decryption(gboolean on_off); - -/* * Adds compiled version string to str */ void diff --git a/caputils/ws80211_utils.c b/caputils/ws80211_utils.c index 7df534617f..6b0e7a8552 100644 --- a/caputils/ws80211_utils.c +++ b/caputils/ws80211_utils.c @@ -381,7 +381,7 @@ static int get_phys_handler(struct nl_msg *msg, void *arg) } added = 1; iface->ifname = ifname; - iface->frequencies = g_array_new(FALSE, FALSE, sizeof(int)); + iface->frequencies = g_array_new(FALSE, FALSE, sizeof(uint32_t)); iface->channel_types = 1 << WS80211_CHAN_NO_HT; } else { g_free(ifname); @@ -587,7 +587,7 @@ static int ws80211_populate_devices(GArray *interfaces) int i; unsigned int j; - struct ws80211_iface_info pub = {-1, WS80211_CHAN_NO_HT}; + struct ws80211_iface_info pub = {-1, WS80211_CHAN_NO_HT, WS80211_FCS_ALL}; struct __iface_info iface_info; struct ws80211_interface *iface; @@ -769,23 +769,6 @@ nla_put_failure: } -void ws80211_free_interfaces(GArray *interfaces) -{ - struct ws80211_interface *iface; - - if (!interfaces) - return; - - while (interfaces->len) { - iface = g_array_index(interfaces, struct ws80211_interface *, 0); - g_array_remove_index(interfaces, 0); - g_array_free(iface->frequencies, TRUE); - g_free(iface->ifname); - g_free(iface); - } - g_array_free(interfaces, TRUE); -} - GArray* ws80211_find_interfaces(void) { GArray *interfaces; @@ -804,17 +787,6 @@ GArray* ws80211_find_interfaces(void) return interfaces; } -int ws80211_frequency_to_channel(int freq) -{ - if (freq == 2484) - return 14; - - if (freq < 2484) - return (freq - 2407) / 5; - - return freq / 5 - 1000; -} - int ws80211_str_to_chan_type(const gchar *s) { @@ -849,32 +821,313 @@ const gchar return NULL; } -#else /* HAVE_LIBNL */ +gboolean ws80211_has_fcs_filter(void) +{ + return FALSE; +} + +int ws80211_set_fcs_validation(const char *name _U_, enum ws80211_fcs_validation fcs_validation _U_) +{ + return -1; +} + +const char *network_manager_path = "/usr/sbin/NetworkManager"; /* Is this correct? */ +const char *ws80211_get_helper_path(void) { + if (g_file_test(network_manager_path, G_FILE_TEST_IS_EXECUTABLE)) { + return network_manager_path; + } + return NULL; +} + +#elif defined(HAVE_AIRPCAP) + +#include <wsutil/unicode-utils.h> + +#include "airpcap.h" +#include "airpcap_loader.h" + int ws80211_init(void) { + if (airpcap_get_dll_state() == AIRPCAP_DLL_OK) { + return 0; + } return -1; } +static const char *airpcap_dev_prefix_ = "\\\\.\\"; + GArray* ws80211_find_interfaces(void) { + GArray *interfaces; + GList *airpcap_if_list, *cur_if; + int err; + gchar *err_str = NULL; + + interfaces = g_array_new(FALSE, FALSE, sizeof(struct ws80211_interface *)); + if (!interfaces) + return NULL; + + airpcap_if_list = get_airpcap_interface_list(&err, &err_str); + + if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){ + g_free(err_str); + g_array_free(interfaces, TRUE); + return NULL; + } + + for (cur_if = airpcap_if_list; cur_if; cur_if = g_list_next(cur_if)) { + struct ws80211_interface *iface; + airpcap_if_info_t *airpcap_if_info = (airpcap_if_info_t *) cur_if->data; + char *ifname; + guint32 chan; + guint32 i; + + if (!airpcap_if_info) continue; + ifname = airpcap_if_info->name; + if (strlen(ifname) > 4 && g_str_has_prefix(ifname, airpcap_dev_prefix_)) ifname += 4; + + iface = (struct ws80211_interface *)g_malloc0(sizeof(*iface)); + iface->ifname = g_strdup(ifname); + iface->can_set_freq = TRUE; + iface->frequencies = g_array_new(FALSE, FALSE, sizeof(guint32)); + + iface->channel_types = 1 << WS80211_CHAN_NO_HT; + /* + * AirPcap stores per-channel capabilities. We should probably + * do the same. */ + for (i = 0; i < airpcap_if_info->numSupportedChannels; i++) { + if (airpcap_if_info->pSupportedChannels[i].Flags & FLAG_CAN_BE_HIGH) { + iface->channel_types |= 1 << WS80211_CHAN_HT40MINUS; + iface->channel_types |= 1 << WS80211_CHAN_HT40PLUS; + break; + } + } + + iface->cap_monitor = 1; + + for (chan = 0; chan < airpcap_if_info->numSupportedChannels; chan++) { + g_array_append_val(iface->frequencies, airpcap_if_info->pSupportedChannels[chan].Frequency); + } + + g_array_append_val(interfaces, iface); + } + + return interfaces; +} + +int ws80211_get_iface_info(const char *name, struct ws80211_iface_info *iface_info) +{ + GList *airpcap_if_list; + int err; + gchar *err_str = NULL; + airpcap_if_info_t *airpcap_if_info; + + if (!iface_info) return -1; + + airpcap_if_list = get_airpcap_interface_list(&err, &err_str); + + if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){ + g_free(err_str); + return -1; + } + + airpcap_if_info = get_airpcap_if_from_name(airpcap_if_list, name); + + if (!airpcap_if_info) { + free_airpcap_interface_list(airpcap_if_list); + return -1; + } + + memset(iface_info, 0, sizeof(*iface_info)); + iface_info->current_freq = airpcap_if_info->channelInfo.Frequency; + switch (airpcap_if_info->channelInfo.ExtChannel) { + case 0: + iface_info->current_chan_type = WS80211_CHAN_NO_HT; + break; + case -1: + iface_info->current_chan_type = WS80211_CHAN_HT40MINUS; + break; + case 1: + iface_info->current_chan_type = WS80211_CHAN_HT40PLUS; + break; + default: + return -1; + } + + switch (airpcap_if_info->CrcValidationOn) { + case AIRPCAP_VT_ACCEPT_CORRECT_FRAMES: + iface_info->current_fcs_validation = WS80211_FCS_VALID; + break; + case AIRPCAP_VT_ACCEPT_CORRUPT_FRAMES: + iface_info->current_fcs_validation = WS80211_FCS_INVALID; + break; + default: + iface_info->current_fcs_validation = WS80211_FCS_ALL; + break; + } + + return 0; +} + +int ws80211_set_freq(const char *name, int freq, int chan_type) +{ + GList *airpcap_if_list; + int err; + gchar *err_str = NULL; + airpcap_if_info_t *airpcap_if_info; + gchar err_buf[AIRPCAP_ERRBUF_SIZE]; + PAirpcapHandle adapter; + int ret_val = -1; + + airpcap_if_list = get_airpcap_interface_list(&err, &err_str); + + if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){ + g_free(err_str); + return ret_val; + } + + airpcap_if_info = get_airpcap_if_from_name(airpcap_if_list, name); + + if (!airpcap_if_info) { + free_airpcap_interface_list(airpcap_if_list); + return ret_val; + } + + adapter = airpcap_if_open(airpcap_if_info->name, err_buf); + if (adapter) { + airpcap_if_info->channelInfo.Frequency = freq; + switch (chan_type) { + case WS80211_CHAN_HT40MINUS: + airpcap_if_info->channelInfo.ExtChannel = -1; + break; + case WS80211_CHAN_HT40PLUS: + airpcap_if_info->channelInfo.ExtChannel = 1; + break; + default: + airpcap_if_info->channelInfo.ExtChannel = 0; + break; + } + + if (airpcap_if_set_device_channel_ex(adapter, airpcap_if_info->channelInfo)) { + ret_val = 0; + } + airpcap_if_close(adapter); + } + + free_airpcap_interface_list(airpcap_if_list); + return ret_val; +} + +int ws80211_str_to_chan_type(const gchar *s _U_) +{ + return -1; +} + +const gchar *ws80211_chan_type_to_str(int type _U_) +{ return NULL; } -int ws80211_get_iface_info(const char *name _U_, struct ws80211_iface_info *iface_info _U_) +gboolean ws80211_has_fcs_filter(void) +{ + return TRUE; +} + +int ws80211_set_fcs_validation(const char *name, enum ws80211_fcs_validation fcs_validation) +{ + GList *airpcap_if_list; + int err; + gchar *err_str = NULL; + airpcap_if_info_t *airpcap_if_info; + gchar err_buf[AIRPCAP_ERRBUF_SIZE]; + PAirpcapHandle adapter; + int ret_val = -1; + + airpcap_if_list = get_airpcap_interface_list(&err, &err_str); + + if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){ + g_free(err_str); + return ret_val; + } + + airpcap_if_info = get_airpcap_if_from_name(airpcap_if_list, name); + + if (!airpcap_if_info) { + free_airpcap_interface_list(airpcap_if_list); + return ret_val; + } + + adapter = airpcap_if_open(airpcap_if_info->name, err_buf); + if (adapter) { + AirpcapValidationType val_type = AIRPCAP_VT_ACCEPT_EVERYTHING; + switch (fcs_validation) { + case WS80211_FCS_VALID: + val_type = AIRPCAP_VT_ACCEPT_CORRECT_FRAMES; + break; + case WS80211_FCS_INVALID: + val_type = AIRPCAP_VT_ACCEPT_CORRUPT_FRAMES; + break; + default: + break; + } + + if (airpcap_if_set_fcs_validation(adapter, val_type)) { + /* Appears to be necessary for this to take effect. */ + airpcap_if_store_cur_config_as_adapter_default(adapter); + ret_val = 0; + } + airpcap_if_close(adapter); + } + + free_airpcap_interface_list(airpcap_if_list); + return ret_val; +} + +static char *airpcap_conf_path = NULL; +const char *ws80211_get_helper_path(void) +{ + HKEY h_key = NULL; + + if (!airpcap_conf_path && RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\AirPcap"), 0, KEY_QUERY_VALUE|KEY_WOW64_32KEY, &h_key) == ERROR_SUCCESS) { + DWORD reg_ret; + TCHAR airpcap_dir_utf16[MAX_PATH]; + DWORD ad_size = sizeof(airpcap_dir_utf16); + + reg_ret = RegQueryValueEx(h_key, NULL, NULL, NULL, + (LPBYTE) &airpcap_dir_utf16, &ad_size); + + if (reg_ret == ERROR_SUCCESS) { + airpcap_dir_utf16[ad_size] = L'\0'; + g_free(airpcap_conf_path); + airpcap_conf_path = g_strdup_printf("%s\\AirpcapConf.exe", utf_16to8(airpcap_dir_utf16)); + + if (!g_file_test(airpcap_conf_path, G_FILE_TEST_IS_EXECUTABLE)) { + g_free(airpcap_conf_path); + airpcap_conf_path = NULL; + } + } + } + + return airpcap_conf_path; +} + +#else /* Everyone else. */ +int ws80211_init(void) { return -1; } -void ws80211_free_interfaces(GArray *interfaces _U_) +GArray* ws80211_find_interfaces(void) { + return NULL; } -int ws80211_frequency_to_channel(int freq _U_) +int ws80211_get_iface_info(const char *name _U_, struct ws80211_iface_info *iface_info _U_) { return -1; } -int ws80211_set_freq(const char *name _U_, int freq _U_, int chan_type _U_) +int ws80211_set_freq(const char *name _U_, int freq _U_, int _U_ chan_type) { return -1; } @@ -888,8 +1141,58 @@ const gchar *ws80211_chan_type_to_str(int type _U_) { return NULL; } + +gboolean ws80211_has_fcs_filter(void) +{ + return FALSE; +} + +int ws80211_set_fcs_validation(const char *name _U_, enum ws80211_fcs_validation fcs_validation _U_) +{ + return -1; +} + +const char *ws80211_get_helper_path(void) { + return NULL; +} + #endif /* HAVE_LIBNL && HAVE_NL80211 */ +/* Common to everyone */ + +void ws80211_free_interfaces(GArray *interfaces) +{ + struct ws80211_interface *iface; + + if (!interfaces) + return; + + while (interfaces->len) { + iface = g_array_index(interfaces, struct ws80211_interface *, 0); + g_array_remove_index(interfaces, 0); + g_array_free(iface->frequencies, TRUE); + g_free(iface->ifname); + g_free(iface); + } + g_array_free(interfaces, TRUE); +} + +int ws80211_frequency_to_channel(int freq) +{ + if (freq == 2484) + return 14; + + if (freq < 2484) + return (freq - 2407) / 5; + + /* 4.9 GHz. https://en.wikipedia.org/wiki/List_of_WLAN_channels, fetched + * 2015-06-15 */ + if (freq < 5000) + return freq / 5 - 800; + + return freq / 5 - 1000; +} + /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * diff --git a/caputils/ws80211_utils.h b/caputils/ws80211_utils.h index 7fcdc4477b..9586cb797f 100644 --- a/caputils/ws80211_utils.h +++ b/caputils/ws80211_utils.h @@ -23,6 +23,10 @@ #ifndef __WS80211_UTILS_H__ #define __WS80211_UTILS_H__ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + enum ws80211_channel_type { WS80211_CHAN_NO_HT, WS80211_CHAN_HT20, @@ -35,28 +39,98 @@ enum ws80211_channel_type { #define CHAN_HT40MINUS "HT40-" #define CHAN_HT40PLUS "HT40+" +/* XXX This doesn't match AirpcapValidationType. Should it? */ +enum ws80211_fcs_validation { + WS80211_FCS_ALL, + WS80211_FCS_VALID, + WS80211_FCS_INVALID +}; + struct ws80211_interface { char *ifname; gboolean can_set_freq; - GArray *frequencies; + gboolean can_check_fcs; + GArray *frequencies; /* Array of guint32? */ int channel_types; /* Union for all bands */ - int cap_monitor; + int cap_monitor; }; struct ws80211_iface_info { - int current_freq; + int current_freq; enum ws80211_channel_type current_chan_type; + enum ws80211_fcs_validation current_fcs_validation; }; - +/** Initialize the 802.11 environment. + * On Linux this initializes an nl80211_state struct. + * On Windows this checks the AirPcap status. It does *not* load the + * AirPcap DLL. That happens when the program starts. + * + * @return 0 on success, an error value on failure. + */ int ws80211_init(void); + +/** Build a list of 802.11 interfaces. + * + * @return A GArray of pointers to struct ws80211_interface on success, NULL on failure. + */ +/* XXX Should we make this an array of structs instead of an array of struct pointers? + * It'd save a bit of mallocing and freeing. */ GArray* ws80211_find_interfaces(void); + int ws80211_get_iface_info(const char *name, struct ws80211_iface_info *iface_info); + +/** Free an interface list. + * + * @param interfaces A list of interfaces created with ws80211_find_interfaces(). + */ void ws80211_free_interfaces(GArray *interfaces); + +/** Convert a frequency to a channel number + * + * @param freq Frequency in MHz. + * @return The 802.11 channel number matching the provided frequency. + */ int ws80211_frequency_to_channel(int freq); + +/** Set the frequency and channel width for an interface. + * + * @param name The interface name. + * @param freq The frequency in MHz. + * @param chan_type + * @return Zero on success, nonzero on failure. + */ int ws80211_set_freq(const char *name, int freq, int chan_type); -int ws80211_str_to_chan_type(const gchar *s); -const gchar *ws80211_chan_type_to_str(int type); + +int ws80211_str_to_chan_type(const gchar *s); /* GTK+ only? */ +const gchar *ws80211_chan_type_to_str(int type); /* GTK+ only? */ + +/** Check to see if we have FCS filtering. + * + * @return TRUE if FCS filtering is supported on this platform. + */ +gboolean ws80211_has_fcs_filter(void); + +/** Set the FCS validation behavior for an interface. + * + * @param name The interface name. + * @param fcs_validation The desired validation behavior. + * @return Zero on success, nonzero on failure. + */ +int ws80211_set_fcs_validation(const char *name, enum ws80211_fcs_validation fcs_validation); + + +/** Get the path to a helper application. + * Return the path to a separate 802.11 helper application, e.g. + * the AirPcap control panel or the GNOME Network Manager. + * + * @return The path to the helper on success, NULL on failure. + */ +const char *ws80211_get_helper_path(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ #endif /* __WS80211_UTILS_H__ */ diff --git a/debian/libwireshark0.symbols b/debian/libwireshark0.symbols index b04268b16e..29f435747a 100644 --- a/debian/libwireshark0.symbols +++ b/debian/libwireshark0.symbols @@ -722,10 +722,7 @@ libwireshark.so.0 libwireshark0 #MINVER# hostlist_table_set_gui_info@Base 1.99.0 http_dissector_add@Base 1.9.1 http_port_add@Base 1.9.1 - ieee80211_chan_to_mhz@Base 1.9.1 ieee80211_float_htrates@Base 1.99.1 - ieee80211_mhz_to_chan@Base 1.9.1 - ieee80211_mhz_to_str@Base 1.9.1 ieee80211_supported_rates_vals_ext@Base 1.99.1 ieee802a_add_oui@Base 1.9.1 in_cksum@Base 1.9.1 diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt index dbd6448012..9de53140fe 100644 --- a/epan/CMakeLists.txt +++ b/epan/CMakeLists.txt @@ -1605,7 +1605,6 @@ set(LIBWIRESHARK_FILES follow.c frame_data.c frame_data_sequence.c - frequency-utils.c funnel.c g_int64_hash_routines.c gcp.c diff --git a/epan/Makefile.common b/epan/Makefile.common index de70f8f8f5..52b772ebd1 100644 --- a/epan/Makefile.common +++ b/epan/Makefile.common @@ -56,7 +56,6 @@ LIBWIRESHARK_SRC = \ follow.c \ frame_data.c \ frame_data_sequence.c \ - frequency-utils.c \ funnel.c \ g_int64_hash_routines.c \ gcp.c \ @@ -196,7 +195,6 @@ LIBWIRESHARK_INCLUDES = \ follow.h \ frame_data.h \ frame_data_sequence.h \ - frequency-utils.h \ funnel.h \ g_int64_hash_routines.h \ garrayfix.h \ diff --git a/epan/dissectors/packet-ieee80211-radiotap.c b/epan/dissectors/packet-ieee80211-radiotap.c index 93a5b7c832..d875f9e9ea 100644 --- a/epan/dissectors/packet-ieee80211-radiotap.c +++ b/epan/dissectors/packet-ieee80211-radiotap.c @@ -30,7 +30,7 @@ #include <epan/packet.h> #include <wsutil/pint.h> #include <epan/crc32-tvb.h> -#include <epan/frequency-utils.h> +#include <wsutil/frequency-utils.h> #include <epan/tap.h> #include <epan/prefs.h> #include <epan/addr_resolv.h> diff --git a/epan/dissectors/packet-ppi.c b/epan/dissectors/packet-ppi.c index 44e3faba27..c6ef8173a4 100644 --- a/epan/dissectors/packet-ppi.c +++ b/epan/dissectors/packet-ppi.c @@ -51,7 +51,7 @@ #include <epan/prefs.h> #include <epan/expert.h> #include <epan/reassemble.h> -#include <epan/frequency-utils.h> +#include <wsutil/frequency-utils.h> #include <wsutil/pint.h> /* Needed for wtap_pcap_encap_to_wtap_encap(). */ diff --git a/ui/gtk/airpcap_dlg.c b/ui/gtk/airpcap_dlg.c index a079d9e006..6ea1fc26f3 100644 --- a/ui/gtk/airpcap_dlg.c +++ b/ui/gtk/airpcap_dlg.c @@ -31,8 +31,9 @@ #include <string.h> #include <wsutil/filesystem.h> +#include <wsutil/frequency-utils.h> + #include <epan/prefs.h> -#include <epan/frequency-utils.h> #include <epan/crypt/wep-wpadefs.h> #include <pcap.h> diff --git a/ui/gtk/airpcap_gui_utils.c b/ui/gtk/airpcap_gui_utils.c index a305bdd983..14d96d5f3f 100644 --- a/ui/gtk/airpcap_gui_utils.c +++ b/ui/gtk/airpcap_gui_utils.c @@ -34,10 +34,19 @@ #include <string.h> #include <wsutil/filesystem.h> +#include <wsutil/frequency-utils.h> + +#include <epan/prefs.h> +#include <epan/prefs-int.h> +#include <epan/uat-int.h> #include <epan/strutil.h> -#include <epan/frequency-utils.h> #include <epan/crypt/airpdcap_ws.h> +#include <epan/crypt/wep-wpadefs.h> + +#include <epan/packet.h> +#include <epan/dissectors/packet-ieee80211.h> +#include "ui/capture_ui_utils.h" #include "ui/simple_dialog.h" #include "ui/gtk/main.h" @@ -56,6 +65,9 @@ /* Controls the releay of settings back to the adapter. */ gboolean change_airpcap_settings = FALSE; +/* WLAN preferences pointer */ +module_t *wlan_prefs = NULL; + /* * Set up the airpcap toolbar for the new capture interface */ @@ -244,6 +256,1309 @@ airpcap_set_toolbar_stop_capture(airpcap_if_info_t* if_info) } } +#if 0 +/* Returs TRUE if the WEP key is valid, false otherwise */ +gboolean +wep_key_is_valid(char* key) +{ + size_t strsize, i; + + if (key == NULL) + return FALSE; + + strsize = strlen(key); + + if ( (strsize > WEP_KEY_MAX_CHAR_SIZE) || (strsize < 2)) + { + return FALSE; + } + if ((strsize % 2) != 0) + { + return FALSE; + } + for(i = 0; i < strsize; i++) + { + if (!g_ascii_isxdigit(key[i])) + { + return FALSE; + } + } + + return TRUE; +} +#endif + +/* + * 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) +{ + gchar *key_string = NULL; + guint8 key_type = AIRPDCAP_KEY_TYPE_WEP; + keys_cb_data_t* user_data; + uat_t *uat; + guint i; + char* err = NULL; + uat_wep_key_record_t* wep_keys; + decryption_key_t* new_key; + + /* Retrieve user data info */ + user_data = (keys_cb_data_t*)ud; + + if (g_ascii_strcasecmp(pref->name, "wep_key_table") == 0 && pref->type == PREF_UAT) + { + uat = pref->varp.uat; + /* This is just a sanity check. UAT should be loaded */ + if (!uat->loaded) + { + if (!uat_load(uat, &err)) + { + /* XXX - report the error */ + g_free(err); + return 1; + } + } + + for (i = 0, wep_keys = (uat_wep_key_record_t*)*uat->user_ptr; i < *uat->nrows_p; i++, wep_keys++) + { + /* strip out key type if present */ + if (g_ascii_strncasecmp(wep_keys->string, STRING_KEY_TYPE_WEP ":", 4) == 0) { + key_type = AIRPDCAP_KEY_TYPE_WEP; + key_string = (gchar*)wep_keys->string+4; + } + else if (g_ascii_strncasecmp(wep_keys->string, STRING_KEY_TYPE_WPA_PWD ":", 8) == 0) { + key_string = (gchar*)wep_keys->string+8; + key_type = AIRPDCAP_KEY_TYPE_WPA_PWD; + } + else if (g_ascii_strncasecmp(wep_keys->string, STRING_KEY_TYPE_WPA_PSK ":", 8) == 0) { + key_string = (gchar*)wep_keys->string+8; + key_type = AIRPDCAP_KEY_TYPE_WPA_PSK; + } + else { + key_type = wep_keys->key; + key_string = (gchar*)wep_keys->string; + } + + /* Here we have the string describing the key... */ + new_key = parse_key_string(key_string, key_type); + + if (new_key != NULL) + { + /* Key is added only if not 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 save_wlan_keys() routine in order to write a decryption key */ +static guint +set_wep_key(pref_t *pref, gpointer ud _U_) +{ + keys_cb_data_t* user_data; + uat_t *uat; + gint i; + char* err = NULL; + uat_wep_key_record_t uat_key; + + decryption_key_t* new_key; + + /* Retrieve user data info */ + user_data = (keys_cb_data_t*)ud; + + if (g_ascii_strcasecmp(pref->name, "wep_key_table") == 0 && pref->type == PREF_UAT) + { + uat = pref->varp.uat; + if (!uat->loaded) + { + /* UAT will only be loaded if previous keys exist, so it may need + to be loaded now */ + if (!uat_load(uat, &err)) + { + /* XXX - report the error */ + g_free(err); + return 1; + } + uat->loaded = 1; + } + /* Free the old records */ + uat_clear(uat); + + for (i = 0; i < user_data->number_of_keys; i++) + { + new_key = (decryption_key_t*)g_list_nth_data(user_data->list,i); + + uat_key.string = get_key_string(new_key); + uat_key.key = new_key->type; + uat_add_record(uat, &uat_key, TRUE); + } + + if (!uat_save(uat, &err)) + { + /* XXX - report the error */ + g_free(err); + return 1; + } + } + + return 0; +} + +/* + * This function will tell the airpcap driver the key list to use + * This will be stored into the registry... + */ +static gboolean +write_wlan_driver_wep_keys_to_registry(GList* key_list) +{ + guint i,j,k,n,y; + GString *new_key; + gchar s[3]; + PAirpcapKeysCollection KeysCollection; + guint KeysCollectionSize; + guint8 KeyByte; + guint keys_in_list = 0; + decryption_key_t* key_item = NULL; + airpcap_if_info_t* fake_info_if = NULL; + + /* Create the fake_info_if from the first adapter of the list */ + fake_info_if = airpcap_driver_fake_if_info_new(); + + if (fake_info_if == NULL) + return FALSE; + + /* + * XXX - When WPA will be supported, change this to: keys_in_list = g_list_length(key_list); + * but right now we will have to count only the WEP keys (or we will have a malloc-mess :-) ) + */ + n = g_list_length(key_list); + for(k = 0; k < n; k++ ) + if (((decryption_key_t*)g_list_nth_data(key_list,k))->type == AIRPDCAP_KEY_TYPE_WEP) + keys_in_list++; + + /* + * Calculate the size of the keys collection + */ + KeysCollectionSize = (guint)AirpcapKeysCollectionSize(keys_in_list); + + /* + * Allocate the collection + */ + KeysCollection = (PAirpcapKeysCollection)g_malloc(KeysCollectionSize); + if (!KeysCollection) + { + return FALSE; + } + + /* + * Populate the key collection + */ + KeysCollection->nKeys = keys_in_list; + + /* + * XXX - If we have, let's say, six keys, the first three are WEP, then two are WPA, and the + * last is WEP, we have to scroll the whole list (n) but increment the array counter only + * when a WEP key is found (y) .. When WPA will be supported by the driver, I'll have to change + * this + */ + y = 0; /* Current position in the key list */ + + for(i = 0; i < n; i++) + { + /* Retrieve the Item corresponding to the i-th key */ + key_item = (decryption_key_t*)g_list_nth_data(key_list,i); + + /* + * XXX - The AIRPDCAP_KEY_TYPE_WEP is the only supported right now! + * We will have to modify the AirpcapKey structure in order to + * support the other two types! What happens now, is that simply the + * not supported keys will just be discarded (they will be saved in Wireshark though) + */ + if (key_item->type == AIRPDCAP_KEY_TYPE_WEP) + { + KeysCollection->Keys[y].KeyType = AIRPDCAP_KEY_TYPE_WEP; + + new_key = g_string_new(key_item->key->str); + + KeysCollection->Keys[y].KeyLen = (guint) new_key->len / 2; + memset(&KeysCollection->Keys[y].KeyData, 0, sizeof(KeysCollection->Keys[y].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 = (guint8)strtol(s, NULL, 16); + KeysCollection->Keys[y].KeyData[j / 2] = KeyByte; + } + /* XXX - Change when WPA will be supported!!! */ + y++; + g_string_free(new_key,TRUE); + } + else if (key_item->type == AIRPDCAP_KEY_TYPE_WPA_PWD) + { + /* XXX - The driver cannot deal with this kind of key yet... */ + } + else if (key_item->type == AIRPDCAP_KEY_TYPE_WPA_PMK) + { + /* XXX - The driver cannot deal with this kind of key yet... */ + } + } + + /* + * Free the old adapter key collection! + */ + if (fake_info_if->keysCollection != NULL) + g_free(fake_info_if->keysCollection); + + /* + * Set this collection ad the new one + */ + fake_info_if->keysCollection = KeysCollection; + fake_info_if->keysCollectionSize = KeysCollectionSize; + + /* + * Configuration must be saved + */ + fake_info_if->saved = FALSE; + + /* + * Write down the changes to the registry + */ + airpcap_save_driver_if_configuration(fake_info_if); + + airpcap_if_info_free(fake_info_if); + + return TRUE; +} + +/* + * Function used to read the Decryption Keys from the preferences and store them + * properly into the airpcap adapter. + */ +static gboolean +load_wlan_driver_wep_keys(void) +{ + keys_cb_data_t* user_data; + guint i; + + /* 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_driver_wep_keys_to_registry(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); + + /* airpcap_if_info_free(fake_info_if); */ + + return TRUE; +} + +/* + * This function will tell the airpcap driver the key list to use + * This will be stored into the registry... + */ +static gboolean +write_wlan_wep_keys_to_registry(airpcap_if_info_t* info_if, GList* key_list) +{ + guint i,j; + GString *new_key; + gchar s[3]; + PAirpcapKeysCollection KeysCollection; + guint KeysCollectionSize; + guint8 KeyByte; + guint keys_in_list = 0; + decryption_key_t* key_item = NULL; + + keys_in_list = g_list_length(key_list); + + /* + * Calculate the size of the keys collection + */ + KeysCollectionSize = (guint)AirpcapKeysCollectionSize(keys_in_list); + + /* + * Allocate the collection + */ + KeysCollection = (PAirpcapKeysCollection)g_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 = AIRPDCAP_KEY_TYPE_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 = (guint) 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 = (guint8)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; +} + +/* + * Returns the ASCII string of a key given the key bytes + */ +static gchar* +airpcap_get_key_string(AirpcapKey key) +{ + unsigned int j = 0; + gchar *dst,*src; + + dst = NULL; + src = NULL; + + if (key.KeyType == AIRPDCAP_KEY_TYPE_WEP) + { + if (key.KeyLen != 0) + { + /* Allocate the string used to store the ASCII representation of the WEP key */ + dst = (gchar*)g_malloc(sizeof(gchar)*WEP_KEY_MAX_CHAR_SIZE + 1); + /* Make sure that the first char is '\0' in order to make g_strlcat() work */ + dst[0]='\0'; + + for(j = 0; j < key.KeyLen; j++) + { + src = g_strdup_printf("%.2x", key.KeyData[j]); + /* + * XXX - use g_strconcat() or GStrings instead ??? + */ + g_strlcat(dst, src, WEP_KEY_MAX_CHAR_SIZE+1); + } + g_free(src); + } + } + else if (key.KeyType == AIRPDCAP_KEY_TYPE_WPA_PWD) + { + /* XXX - Add code here */ + } + else if (key.KeyType == AIRPDCAP_KEY_TYPE_WPA_PMK) + { + /* XXX - Add code here */ + } + else + { + /* XXX - Add code here */ + } + + return dst; +} + +/* + * Function used to save to the preference file the Decryption Keys. + */ +static int +save_wlan_driver_wep_keys(void) +{ + GList* key_list = NULL; + char* tmp_key = NULL; + guint keys_in_list,i; + keys_cb_data_t* user_data; + airpcap_if_info_t* fake_info_if = NULL; + + /* Create the fake_info_if from the first adapter of the list */ + fake_info_if = airpcap_driver_fake_if_info_new(); + + if (fake_info_if == NULL) + return 0; + + /* 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 */ + if (fake_info_if->keysCollectionSize != 0) + keys_in_list = AirpcapKeysCollectionSizeToKeyCount(fake_info_if->keysCollectionSize); + else + keys_in_list = 0; + + for(i=0; i<keys_in_list; i++) + { + /* Only if it is a WEP key... */ + if (fake_info_if->keysCollection->Keys[i].KeyType == AIRPDCAP_KEY_TYPE_WEP) + { + tmp_key = airpcap_get_key_string(fake_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); + + airpcap_if_info_free(fake_info_if); + + return keys_in_list; +} + +/* + * Function used to save to the preference file the Decryption Keys. + */ +static int +save_wlan_wireshark_wep_keys(GList* key_ls) +{ + GList* key_list = NULL; + guint keys_in_list,i; + keys_cb_data_t* user_data; + decryption_key_t* tmp_dk; + + /* 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)); + + keys_in_list = g_list_length(key_ls); + + key_list = key_ls; + + /* 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++) + { + tmp_dk = (decryption_key_t*)g_list_nth(user_data->list,i)->data; + g_string_free(tmp_dk->key,TRUE); + if (tmp_dk->ssid != NULL) g_byte_array_free(tmp_dk->ssid,TRUE); + } + + /* free the (empty) list */ + g_list_free(user_data->list); + + /* free the user_data structure */ + g_free(user_data); + + return keys_in_list; +} + +/* + * Returns the default airpcap interface of a list, NULL if list is empty + */ +airpcap_if_info_t* +airpcap_get_default_if(GList* airpcap_if_list_p) +{ + airpcap_if_info_t* if_info = NULL; + + if ((prefs.capture_device != NULL) && (*prefs.capture_device != '\0')) + { + if_info = get_airpcap_if_from_name(airpcap_if_list_p, + get_if_name(prefs.capture_device)); + } + return if_info; +} + +/* + * DECRYPTION KEYS FUNCTIONS + */ +#if 0 +/* + * This function is used for DEBUG POURPOSES ONLY!!! + */ +void +print_key_list(GList* key_list) +{ + gint n,i; + decryption_key_t* tmp; + + if (key_list == NULL) + { + g_print("\n\n******* KEY LIST NULL *******\n\n"); + return; + } + + 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 == AIRPDCAP_KEY_TYPE_WEP) + g_print("TYPE: %s\n",AIRPCAP_WEP_KEY_STRING); + else if (tmp->type == AIRPDCAP_KEY_TYPE_WPA_PWD) + g_print("TYPE: %s\n",AIRPCAP_WPA_PWD_KEY_STRING); + else if (tmp->type == AIRPDCAP_KEY_TYPE_WPA_PMK) + g_print("TYPE: %s\n",AIRPCAP_WPA_BIN_KEY_STRING); + else + g_print("TYPE: %s\n","???"); + + g_print("SSID: %s\n",(tmp->ssid != NULL) ? + format_text((guchar *)tmp->ssid->data, tmp->ssid->len) : "---"); + g_print("\n"); + } + + g_print("\n*****************************\n\n"); +} +#endif + +/* + * 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 = AirpcapKeysCollectionSizeToKeyCount(info_if->keysCollectionSize); + 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 == AIRPDCAP_KEY_TYPE_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 = (guint) new_key->key->len *4; /* every char is 4 bits in WEP keys (it is an hexadecimal 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 == AIRPDCAP_KEY_TYPE_WPA_PWD) + { + /* XXX - Not supported yet */ + } + else if (info_if->keysCollection->Keys[i].KeyType == AIRPDCAP_KEY_TYPE_WPA_PMK) + { + /* XXX - Not supported yet */ + } + } + + return key_list; +} + +/* + * Retrieves a GList of decryption_key_t structures containing infos about the + * keys for the global AirPcap driver... returns NULL if no keys are found. + */ +GList * +get_airpcap_driver_keys(void) +{ + /* tmp vars */ + char *tmp_key = NULL; + guint i,keys_in_list = 0; + + /* real vars*/ + decryption_key_t *new_key = NULL; + GList *key_list = NULL; + + /* + * To read the drivers general settings we need to create and use one airpcap adapter... + * The only way to do that is to instantiate a fake adapter, and then close it and delete it. + */ + airpcap_if_info_t* fake_info_if = NULL; + + /* Create the fake_info_if from the first adapter of the list */ + fake_info_if = airpcap_driver_fake_if_info_new(); + + if (fake_info_if == NULL) + return NULL; + + /* Number of keys in key list */ + if (fake_info_if->keysCollectionSize != 0) + keys_in_list = AirpcapKeysCollectionSizeToKeyCount(fake_info_if->keysCollectionSize); + else + keys_in_list = 0; + + for(i=0; i<keys_in_list; i++) + { + /* Different things to do depending on the key type */ + if (fake_info_if->keysCollection->Keys[i].KeyType == AIRPDCAP_KEY_TYPE_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(fake_info_if->keysCollection->Keys[i]); + new_key->key = g_string_new(tmp_key); + if (tmp_key != NULL) g_free(tmp_key); + + /* BITS */ + new_key->bits = (guint) new_key->key->len *4; /* every char is 4 bits in WEP keys (it is an hexadecimal number) */ + + /* SSID not used in WEP keys */ + new_key->ssid = NULL; + + /* TYPE (WEP in this case) */ + new_key->type = fake_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 (fake_info_if->keysCollection->Keys[i].KeyType == AIRPDCAP_KEY_TYPE_WPA_PWD) + { + /* XXX - Not supported yet */ + } + else if (fake_info_if->keysCollection->Keys[i].KeyType == AIRPDCAP_KEY_TYPE_WPA_PMK) + { + /* XXX - Not supported yet */ + } + } + + airpcap_if_info_free(fake_info_if); + + return key_list; +} + +/* + * Returns the list of the decryption keys specified for wireshark, NULL if + * no key is found + */ +GList * +get_wireshark_keys(void) +{ + keys_cb_data_t *wep_user_data = NULL; + + GList *final_list = NULL; + GList *wep_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); + + /* Copy the list field in the user data structure pointer into the final_list */ + wep_final_list = wep_user_data->list; + + /* XXX - Merge the three lists!!!!! */ + final_list = wep_final_list; + + /* free the wep_user_data structure */ + g_free(wep_user_data); + + return final_list; +} + + +static guint +test_if_on(pref_t *pref, gpointer ud) +{ + gboolean *is_on; + gboolean number; + + /* Retrieve user data info */ + is_on = (gboolean*)ud; + + + if (g_ascii_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; +} + +/* + * 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) + { + 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); + new_dk->ssid = byte_array_dup(dk2->ssid); + + /* 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); + + 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); + new_dk->ssid = byte_array_dup(dk1->ssid); + + /* 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); + new_dk->ssid = byte_array_dup(dk1->ssid); + + /* 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); + new_dk->ssid = byte_array_dup(dk2->ssid); + + /* 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_byte_array_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; + + /* XXX - Remove this check when we will have the WPA/WPA2 decryption in the Driver! */ + /** if ( (k1->type == AIRPDCAP_KEY_TYPE_WPA_PWD) || (k2->type == AIRPDCAP_KEY_TYPE_WPA_PWD) || (k1->type == AIRPDCAP_KEY_TYPE_WPA_PMK) || (k2->type == AIRPDCAP_KEY_TYPE_WPA_PMK) ) **/ + /** return TRUE; **/ + + 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; + + /* If they are not null, they must share the same ssid */ + return byte_array_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; + /* XXX - Remove */ + guint wep_n1 = 0,wep_n2=0; + GList *wep_list1 = NULL; + GList *wep_list2 = NULL; + /* XXX - END*/ + guint i/*,j*/; + decryption_key_t *dk1=NULL,*dk2=NULL; + + n1 = g_list_length(list1); + n2 = g_list_length(list2); + + /* + * XXX - START : Retrieve the aublists of WEP keys!!! This is needed only 'till Driver WPA decryption + * is implemented. + */ + for(i=0;i<n1;i++) + { + dk1=(decryption_key_t*)g_list_nth_data(list1,i); + if (dk1->type == AIRPDCAP_KEY_TYPE_WEP) + { + wep_list1 = g_list_append(wep_list1,(gpointer)dk1); + wep_n1++; + } + } + for(i=0;i<n2;i++) + { + dk2=(decryption_key_t*)g_list_nth_data(list2,i); + if (dk2->type == AIRPDCAP_KEY_TYPE_WEP) + { + wep_list2 = g_list_append(wep_list2,(gpointer)dk2); + wep_n2++; + } + } + + /* + * XXX - END : Remove from START to END when the WPA/WPA2 decryption will be implemented in + * the Driver + */ + + /* + * Commented, because in the new AirPcap version all the keys will be saved + * into the driver, and all the keys for every specific adapter will be + * removed. This means that this check will always fail... and the user will + * always be asked what to do... and it doesn't make much sense. + */ + /* if (n1 != n2) return FALSE; */ + if (wep_n1 != wep_n2) return FALSE; + + n2 = wep_n2; + + /*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; + }*/ + for(i=0;i<n2;i++) + { + dk2=(decryption_key_t*)g_list_nth_data(wep_list2,i); + if (!key_is_in_list(dk2,wep_list1)) return FALSE; + } + + return TRUE; +} + + +/* + * Returns TRUE if the Wireshark decryption is active, false otherwise + * XXX - Should we just add a routine to packet-ieee80211.c to grab this directly? + */ +gboolean +wireshark_decryption_on(void) +{ + 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 for the current adapter is active, false otherwise + */ +gboolean +airpcap_decryption_on(void) +{ + gboolean is_on = FALSE; + + airpcap_if_info_t* fake_if_info = NULL; + + fake_if_info = airpcap_driver_fake_if_info_new(); + + if (fake_if_info != NULL) + { + if (fake_if_info->DecryptionOn == AIRPCAP_DECRYPTION_ON) + is_on = TRUE; + else if (fake_if_info->DecryptionOn == AIRPCAP_DECRYPTION_OFF) + is_on = FALSE; + } + + airpcap_if_info_free(fake_if_info); + + return is_on; +} + +static guint +set_on_off(pref_t *pref, gpointer ud) +{ + gboolean *is_on; + + /* Retrieve user data info */ + is_on = (gboolean*)ud; + + if (g_ascii_strncasecmp(pref->name, "enable_decryption", 17) == 0 && pref->type == PREF_BOOL) + { + + 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 .dll functions here... */ + gchar ebuf[AIRPCAP_ERRBUF_SIZE]; + PAirpcapHandle ad,ad_driver; + + gboolean success = TRUE; + + gint n = 0; + gint i = 0; + airpcap_if_info_t* curr_if = NULL; + airpcap_if_info_t* fake_if_info = NULL; + + fake_if_info = airpcap_driver_fake_if_info_new(); + + if (fake_if_info == NULL) + /* We apparently don't have any adapters installed. + * This isn't a failure, so return TRUE + */ + return TRUE; + + /* Set the driver decryption */ + ad_driver = airpcap_if_open(fake_if_info->name, ebuf); + if (ad_driver) + { + if (on_off) + airpcap_if_set_driver_decryption_state(ad_driver,AIRPCAP_DECRYPTION_ON); + else + airpcap_if_set_driver_decryption_state(ad_driver,AIRPCAP_DECRYPTION_OFF); + + airpcap_if_close(ad_driver); + } + + airpcap_if_info_free(fake_if_info); + + n = g_list_length(airpcap_if_list); + + /* Set to FALSE the decryption for 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(curr_if->name, ebuf); + if (ad) + { + curr_if->DecryptionOn = AIRPCAP_DECRYPTION_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; +} + + + /* * Add a key (string) to the given list */ diff --git a/ui/gtk/airpcap_gui_utils.h b/ui/gtk/airpcap_gui_utils.h index 3238312edf..d5cd0a0632 100644 --- a/ui/gtk/airpcap_gui_utils.h +++ b/ui/gtk/airpcap_gui_utils.h @@ -214,4 +214,92 @@ airpcap_save_decryption_keys(GList* key_list, GList* adapters_list); void airpcap_enable_toolbar_widgets(GtkWidget* w, gboolean en); +/* + * Returns the default airpcap interface of a list, NULL if list is empty + */ +airpcap_if_info_t* +airpcap_get_default_if(GList* airpcap_if_list); + +/* + * DECRYPTION KEYS FUNCTIONS + */ + +/* + * 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* if_info); + +/* + * Retrieves a GList of decryption_key_t structures containing infos about the + * keys for the global AirPcap driver... returns NULL if no keys are found. + */ +GList* +get_airpcap_driver_keys(void); + +/* + * Returns the list of the decryption keys specified for wireshark, NULL if + * no key is found + */ +GList* +get_wireshark_keys(void); + +/* + * 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); + +/* + * Merges two lists of keys. If a key is found multiple times, it will just appear once! + */ +GList* +merge_key_list(GList* list1, GList* list2); + +/* + * 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); + +/* + * Returns TRUE if keys are equals, FALSE otherwise + */ +gboolean +keys_are_equals(decryption_key_t *k1,decryption_key_t *k2); + +/* + * Use this function to free a key list. + */ +void +free_key_list(GList *list); + +/* + * Returns TRUE if the Wireshark decryption is active, FALSE otherwise + */ +gboolean +wireshark_decryption_on(void); + +/* + * Returns TRUE if the AirPcap decryption for the current adapter is active, FALSE otherwise + */ +gboolean +airpcap_decryption_on(void); + +/* + * Enables decryption for Wireshark if on_off is TRUE, disables it otherwise. + */ +void +set_wireshark_decryption(gboolean on_off); + +/* + * Enables decryption for all the adapters if on_off is TRUE, disables it otherwise. + */ +gboolean +set_airpcap_decryption(gboolean on_off); + #endif diff --git a/ui/gtk/main.c b/ui/gtk/main.c index 6b73413230..d0c3b47c9c 100644 --- a/ui/gtk/main.c +++ b/ui/gtk/main.c @@ -80,7 +80,6 @@ #include <epan/ex-opt.h> #include <epan/funnel.h> #include <epan/expert.h> -#include <epan/frequency-utils.h> #include <epan/prefs.h> #include <epan/prefs-int.h> #include <epan/tap.h> @@ -96,6 +95,7 @@ #endif #include <wsutil/cmdarg_err.h> +#include <wsutil/frequency-utils.h> #include <wsutil/plugins.h> /* general (not GTK specific) */ diff --git a/ui/gtk/main_airpcap_toolbar.c b/ui/gtk/main_airpcap_toolbar.c index 44cb20a57e..0f3f8374ee 100644 --- a/ui/gtk/main_airpcap_toolbar.c +++ b/ui/gtk/main_airpcap_toolbar.c @@ -32,7 +32,8 @@ #include "ui/gtk/old-gtk-compat.h" #include "epan/epan.h" -#include "epan/frequency-utils.h" + +#include "wsutil/frequency-utils.h" #include "ui/recent.h" #include "simple_dialog.h" diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt index 712c02e250..face9b58d6 100644 --- a/ui/qt/CMakeLists.txt +++ b/ui/qt/CMakeLists.txt @@ -111,6 +111,7 @@ set(WIRESHARK_QT_HEADERS traffic_table_dialog.h uat_dialog.h voip_calls_dialog.h + wireless_frame.h wireshark_application.h wireshark_dialog.h ) @@ -229,6 +230,7 @@ set(WIRESHARK_QT_SRC traffic_table_dialog.cpp uat_dialog.cpp voip_calls_dialog.cpp + wireless_frame.cpp wireshark_application.cpp wireshark_dialog.cpp ) @@ -319,6 +321,7 @@ set(WIRESHARK_QT_UI traffic_table_dialog.ui uat_dialog.ui voip_calls_dialog.ui + wireless_frame.ui ) if(HAVE_PCAP_REMOTE) diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am index 1205b77f79..9c3aacf77e 100644 --- a/ui/qt/Makefile.am +++ b/ui/qt/Makefile.am @@ -238,6 +238,8 @@ uat_dialog.cpp uat_dialog.h: ui_uat_dialog.h voip_calls_dialog.cpp voip_calls_dialog.h: ui_voip_calls_dialog.h +wireless_frame.cpp wireless_frame.h: ui_wireless_frame.h + doxygen: if HAVE_DOXYGEN $(DOXYGEN) doxygen.cfg diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common index ac1335bf53..cf9ec50e93 100644 --- a/ui/qt/Makefile.common +++ b/ui/qt/Makefile.common @@ -87,7 +87,8 @@ NODIST_GENERATED_HEADER_FILES = \ ui_time_shift_dialog.h \ ui_traffic_table_dialog.h \ ui_uat_dialog.h \ - ui_voip_calls_dialog.h + ui_voip_calls_dialog.h \ + ui_wireless_frame.h # Generated C source files that we want in the distribution. GENERATED_C_FILES = \ @@ -217,6 +218,7 @@ MOC_HDRS = \ traffic_table_dialog.h \ uat_dialog.h \ voip_calls_dialog.h \ + wireless_frame.h \ wireshark_application.h \ wireshark_dialog.h @@ -283,7 +285,8 @@ UI_FILES = \ time_shift_dialog.ui \ traffic_table_dialog.ui \ uat_dialog.ui \ - voip_calls_dialog.ui + voip_calls_dialog.ui \ + wireless_frame.ui # # The .moc.cpp files generated from them. @@ -433,6 +436,7 @@ WIRESHARK_QT_SRC = \ traffic_table_dialog.cpp \ uat_dialog.cpp \ voip_calls_dialog.cpp \ + wireless_frame.cpp \ wireshark_application.cpp \ wireshark_dialog.cpp diff --git a/ui/qt/Wireshark.pro b/ui/qt/Wireshark.pro index 9da9457968..002652128f 100644 --- a/ui/qt/Wireshark.pro +++ b/ui/qt/Wireshark.pro @@ -263,7 +263,8 @@ FORMS += \ time_shift_dialog.ui \ traffic_table_dialog.ui \ uat_dialog.ui \ - voip_calls_dialog.ui + voip_calls_dialog.ui \ + wireless_frame.ui HEADERS += $$HEADERS_WS_C \ @@ -327,7 +328,8 @@ HEADERS += $$HEADERS_WS_C \ tcp_stream_dialog.h \ traffic_table_dialog.h \ uat_dialog.h \ - voip_calls_dialog.h + voip_calls_dialog.h \ + wireless_frame.h win32 { OBJECTS_WS_C = $$SOURCES_WS_C @@ -710,6 +712,7 @@ SOURCES += \ traffic_table_dialog.cpp \ uat_dialog.cpp \ voip_calls_dialog.cpp \ + wireless_frame.cpp \ wireshark_application.cpp \ wireshark_dialog.cpp \ ../../wireshark-qt.cpp diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index 086d8a5a4e..53d9d7ae52 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -51,6 +51,7 @@ #include "proto_tree.h" #include "simple_dialog.h" #include "stock_icon.h" +#include "wireless_frame.h" #include "wireshark_application.h" #include "qt_ui_utils.h" @@ -232,6 +233,13 @@ MainWindow::MainWindow(QWidget *parent) : // This property is obsolete in Qt5 so this issue may be fixed in that version. main_ui_->displayFilterToolBar->insertWidget(main_ui_->actionDisplayFilterExpression, df_combo_box_); + wireless_frame_ = new WirelessFrame(this); + main_ui_->wirelessToolBar->addWidget(wireless_frame_); + connect(wireless_frame_, SIGNAL(pushAdapterStatus(const QString&)), + main_ui_->statusBar, SLOT(pushTemporaryStatus(const QString&))); + connect (wireless_frame_, SIGNAL(showWirelessPreferences(QString)), + this, SLOT(showPreferencesDialog(QString))); + main_ui_->goToFrame->hide(); // XXX For some reason the cursor is drawn funny with an input mask set // https://bugreports.qt-project.org/browse/QTBUG-7174 @@ -1507,7 +1515,7 @@ void MainWindow::initShowHideMainWidgets() show_hide_actions_->setExclusive(false); shmw_actions[main_ui_->actionViewMainToolbar] = main_ui_->mainToolBar; shmw_actions[main_ui_->actionViewFilterToolbar] = main_ui_->displayFilterToolBar; - shmw_actions[main_ui_->actionViewWirelessToolbar] = NULL; // Doesn't exist yet. + shmw_actions[main_ui_->actionViewWirelessToolbar] = main_ui_->wirelessToolBar; shmw_actions[main_ui_->actionViewStatusBar] = main_ui_->statusBar; shmw_actions[main_ui_->actionViewPacketList] = packet_list_; shmw_actions[main_ui_->actionViewPacketDetails] = proto_tree_; @@ -1879,6 +1887,8 @@ void MainWindow::setForCaptureInProgress(gboolean capture_in_progress) { setMenusForCaptureInProgress(capture_in_progress); + wireless_frame_->setCaptureInProgress(capture_in_progress); + #ifdef HAVE_LIBPCAP packet_list_->setCaptureInProgress(capture_in_progress); // set_toolbar_for_capture_in_progress(capture_in_progress); diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index 37431d4b61..2942fa66d6 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -63,6 +63,7 @@ class ByteViewTab; class MainWelcome; class PacketList; class ProtoTree; +class WirelessFrame; class QAction; class QActionGroup; @@ -120,6 +121,7 @@ private: DisplayFilterCombo *df_combo_box_; CaptureFile capture_file_; QFont mono_font_; + WirelessFrame *wireless_frame_; // XXX - packet_list_, proto_tree_, and byte_view_tab_ should // probably be full-on values instead of pointers. PacketList *packet_list_; diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui index de8489c108..3f06b2894b 100644 --- a/ui/qt/main_window.ui +++ b/ui/qt/main_window.ui @@ -110,7 +110,7 @@ <x>0</x> <y>0</y> <width>960</width> - <height>22</height> + <height>21</height> </rect> </property> <widget class="QMenu" name="menuFile"> @@ -609,6 +609,17 @@ </attribute> <addaction name="actionDisplayFilterExpression"/> </widget> + <widget class="QToolBar" name="wirelessToolBar"> + <property name="movable"> + <bool>false</bool> + </property> + <attribute name="toolBarArea"> + <enum>TopToolBarArea</enum> + </attribute> + <attribute name="toolBarBreak"> + <bool>true</bool> + </attribute> + </widget> <action name="actionFileOpen"> <property name="text"> <string>Open</string> @@ -2153,18 +2164,12 @@ <property name="checkable"> <bool>true</bool> </property> - <property name="checked"> - <bool>true</bool> - </property> <property name="text"> <string>Wire&less Toolbar</string> </property> <property name="toolTip"> <string>Show or hide the wireless toolbar</string> </property> - <property name="visible"> - <bool>false</bool> - </property> </action> <action name="actionViewStatusBar"> <property name="checkable"> diff --git a/ui/qt/wireless_frame.cpp b/ui/qt/wireless_frame.cpp new file mode 100644 index 0000000000..c56a8b317d --- /dev/null +++ b/ui/qt/wireless_frame.cpp @@ -0,0 +1,313 @@ +/* wireless_frame.cpp + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "wireless_frame.h" +#include "ui_wireless_frame.h" + +#include "config.h" + +#include <glib.h> + +#include <capchild/capture_session.h> +#include <capchild/capture_sync.h> + +#include <caputils/ws80211_utils.h> + +#include <ui/ui_util.h> +#include <ui/utf8_entities.h> + +#include <QProcess> + +// To do: +// - Disable or hide invalid channel types. +// - Push more status messages ("switched to...") to the status bar. +// - Add a "Decrypt in the driver" checkbox? +// - Check for frequency and channel type changes. + +// Questions: +// - From our perspective, what's the difference between "NOHT" and "HT20"? + +const int update_interval_ = 1500; // ms + +WirelessFrame::WirelessFrame(QWidget *parent) : + QFrame(parent), + ui(new Ui::WirelessFrame), + interfaces_(NULL), + capture_in_progress_(false) +{ + ui->setupUi(this); + + ui->helperToolButton->hide(); + + if (ws80211_init() == 0) { + ui->stackedWidget->setEnabled(true); + ui->stackedWidget->setCurrentWidget(ui->interfacePage); + +#ifdef Q_OS_WIN + // We should arguably add ws80211_get_helper_name and ws80211_get_helper_tooltip. + // This works for now and is translatable. + ui->helperToolButton->setText(tr("AirPcap Control Panel")); + ui->helperToolButton->setToolTip(tr("Open the AirPcap Control Panel")); + ui->helperToolButton->show(); + ui->helperToolButton->setEnabled(ws80211_get_helper_path() != NULL); +#endif + + } else { + ui->stackedWidget->setEnabled(false); + ui->stackedWidget->setCurrentWidget(ui->noWirelessPage); + } + + ui->fcsFilterFrame->setVisible(ws80211_has_fcs_filter()); + + updateWidgets(); + startTimer(update_interval_); +} + +WirelessFrame::~WirelessFrame() +{ + delete ui; +} + +void WirelessFrame::setCaptureInProgress(bool capture_in_progress) +{ + capture_in_progress_ = capture_in_progress; + updateWidgets(); +} + +// Check to see if the ws80211 interface list matches the one in our +// combobox. Rebuild ours if necessary and select the first interface if +// the current selection goes away. +void WirelessFrame::timerEvent(QTimerEvent *) +{ + ws80211_free_interfaces(interfaces_); + interfaces_ = ws80211_find_interfaces(); + const QString old_iface = ui->interfaceComboBox->currentText(); + guint iface_count = 0; + bool list_changed = false; + + if (interfaces_ && interfaces_->len > 0) { + iface_count = interfaces_->len; + } + + if ((int) iface_count != ui->interfaceComboBox->count()) { + list_changed = true; + } else { + for (guint i = 0; i < iface_count; i++) { + struct ws80211_interface *iface = g_array_index(interfaces_, struct ws80211_interface *, i); + if (ui->interfaceComboBox->itemText(i).compare(iface->ifname) != 0) { + list_changed = true; + break; + } + } + } + + if (list_changed) { + ui->interfaceComboBox->clear(); + for (guint i = 0; i < iface_count; i++) { + struct ws80211_interface *iface = g_array_index(interfaces_, struct ws80211_interface *, i); + ui->interfaceComboBox->addItem(iface->ifname); + if (old_iface.compare(iface->ifname) == 0) { + ui->interfaceComboBox->setCurrentIndex(ui->interfaceComboBox->count() - 1); + } + } + } + + if (ui->interfaceComboBox->currentText().compare(old_iface) != 0) { + on_channelComboBox_activated(ui->interfaceComboBox->currentIndex()); + } +} + +Q_DECLARE_METATYPE(struct ws80211_interface *) +void WirelessFrame::updateWidgets() +{ + bool enable_interface = false; + bool enable_channel = false; + bool enable_offset = false; + bool enable_show_fcs = false; + + if (ui->interfaceComboBox->count() > 0) { + enable_interface = true; + enable_show_fcs = true; + } + + if (enable_interface && ui->channelComboBox->count() > 0) { + enable_channel = true; + } + + if (enable_channel && ui->channelTypeComboBox->count() > 1) { + enable_offset = true; + } + + ui->interfaceComboBox->setEnabled(enable_interface); + ui->channelComboBox->setEnabled(enable_channel); + ui->channelTypeComboBox->setEnabled(enable_offset); + ui->fcsComboBox->setEnabled(!capture_in_progress_ && enable_show_fcs); +} + +void WirelessFrame::on_helperToolButton_clicked() +{ + const QString helper_path = ws80211_get_helper_path(); + if (helper_path.isEmpty()) return; + + QString command = QString("\"%1\"").arg(helper_path); + QProcess::startDetached(command); +} + +void WirelessFrame::on_prefsToolButton_clicked() +{ + emit showWirelessPreferences(QString("wlan")); +} + +void WirelessFrame::on_interfaceComboBox_currentIndexChanged(const QString &cur_iface) +{ + ui->channelComboBox->clear(); + ui->channelTypeComboBox->clear(); + if (cur_iface.isEmpty()) { + updateWidgets(); + return; + } + + for (guint i = 0; i < interfaces_->len; i++) { + struct ws80211_interface *iface = g_array_index(interfaces_, struct ws80211_interface *, i); + if (cur_iface.compare(iface->ifname) == 0) { + struct ws80211_iface_info iface_info; + QString units = " GHz"; + + ws80211_get_iface_info(iface->ifname, &iface_info); + + for (guint i = 0; i < iface->frequencies->len; i++) { + guint32 frequency = g_array_index(iface->frequencies, guint32, i); + double ghz = frequency / 1000.0; + QString chan_str = QString("%1 " UTF8_MIDDLE_DOT " %2%3") + .arg(ws80211_frequency_to_channel(frequency)) + .arg(ghz, 0, 'f', 3) + .arg(units); + ui->channelComboBox->addItem(chan_str, frequency); + if ((int)frequency == iface_info.current_freq) { + ui->channelComboBox->setCurrentIndex(ui->channelComboBox->count() - 1); + } + units = QString(); + } + // XXX - Do we need to make a distinction between WS80211_CHAN_NO_HT + // and WS80211_CHAN_HT20? E.g. is there a driver that won't capture + // HT frames if you use WS80211_CHAN_NO_HT? + ui->channelTypeComboBox->addItem("20 MHz", WS80211_CHAN_NO_HT); + if (iface_info.current_chan_type == WS80211_CHAN_NO_HT || iface_info.current_chan_type == WS80211_CHAN_HT20) { + ui->channelTypeComboBox->setCurrentIndex(0); + } + if (iface->channel_types & (1 << WS80211_CHAN_HT40MINUS)) { + ui->channelTypeComboBox->addItem("HT 40-", WS80211_CHAN_HT40MINUS); + if (iface_info.current_chan_type == WS80211_CHAN_HT40MINUS) { + ui->channelTypeComboBox->setCurrentIndex(ui->channelTypeComboBox->count() - 1); + } + } + if (iface->channel_types & (1 << WS80211_CHAN_HT40PLUS)) { + ui->channelTypeComboBox->addItem("HT 40+", WS80211_CHAN_HT40PLUS); + if (iface_info.current_chan_type == WS80211_CHAN_HT40PLUS) { + ui->channelTypeComboBox->setCurrentIndex(ui->channelTypeComboBox->count() - 1); + } + } + + if (ws80211_has_fcs_filter()) { + ui->fcsComboBox->setCurrentIndex(iface_info.current_fcs_validation); + } + } + } + updateWidgets(); +} + +void WirelessFrame::setChannel() +{ + QString cur_iface = ui->interfaceComboBox->currentText(); + int cur_chan_idx = ui->channelComboBox->currentIndex(); + int cur_type_idx = ui->channelTypeComboBox->currentIndex(); + + if (cur_iface.isEmpty() || cur_chan_idx < 0 || cur_type_idx < 0) return; + +#ifdef Q_OS_WIN + int frequency = ui->channelComboBox->itemData(cur_chan_idx).toInt(); + int chan_type = ui->channelTypeComboBox->itemData(cur_type_idx).toInt(); + if (frequency < 0 || chan_type < 0) return; + + if (ws80211_set_freq(cur_iface.toUtf8().constData(), frequency, chan_type) != 0) { + QString err_str = tr("Unable to set channel or offset."); + emit pushAdapterStatus(err_str); + } +#else // Assume we have to go through dumpcap. + const QString frequency = ui->channelComboBox->itemData(cur_chan_idx).toString(); + int chan_type = ui->channelTypeComboBox->itemData(cur_type_idx).toInt(); + const gchar *chan_type_s = ws80211_chan_type_to_str(chan_type); + gchar *data, *primary_msg, *secondary_msg; + int ret; + + if (frequency.isEmpty() || chan_type < 0) return; + + ret = sync_interface_set_80211_chan(cur_iface.toUtf8().constData(), frequency.toUtf8().constData(), chan_type_s, + &data, &primary_msg, &secondary_msg, main_window_update); + + g_free(data); + g_free(primary_msg); + g_free(secondary_msg); + + /* Parse the error msg */ + if (ret) { + QString err_str = tr("Unable to set channel or offset."); + emit pushAdapterStatus(err_str); + } +#endif + + updateWidgets(); +} + +void WirelessFrame::on_channelComboBox_activated(int) +{ + setChannel(); +} + +void WirelessFrame::on_channelTypeComboBox_activated(int) +{ + setChannel(); +} + +void WirelessFrame::on_fcsComboBox_activated(int index) +{ + QString cur_iface = ui->interfaceComboBox->currentText(); + if (cur_iface.isEmpty()) return; + + if (ws80211_set_fcs_validation(cur_iface.toUtf8().constData(), (enum ws80211_fcs_validation) index) != 0) { + QString err_str = tr("Unable to set FCS validation behavior."); + emit pushAdapterStatus(err_str); + } + updateWidgets(); +} + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/ui/qt/wireless_frame.h b/ui/qt/wireless_frame.h new file mode 100644 index 0000000000..d9249ea647 --- /dev/null +++ b/ui/qt/wireless_frame.h @@ -0,0 +1,83 @@ +/* wireless_frame.h + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef WIRELESS_FRAME_H +#define WIRELESS_FRAME_H + +#include <glib.h> + +#include <QFrame> + +namespace Ui { +class WirelessFrame; +} + +class WirelessFrame : public QFrame +{ + Q_OBJECT + +public: + explicit WirelessFrame(QWidget *parent = 0); + ~WirelessFrame(); + + void setCaptureInProgress(bool capture_in_progress); + +signals: + void pushAdapterStatus(const QString&); + void showWirelessPreferences(const QString wlan_module_name); + +protected: + void timerEvent(QTimerEvent *); + +private: + void setChannel(); + +private slots: + void updateWidgets(); + + void on_helperToolButton_clicked(); + void on_prefsToolButton_clicked(); + void on_interfaceComboBox_currentIndexChanged(const QString &cur_iface); + void on_channelComboBox_activated(int); + void on_channelTypeComboBox_activated(int); + + void on_fcsComboBox_activated(int index); + +private: + Ui::WirelessFrame *ui; + GArray *interfaces_; + bool capture_in_progress_; +}; + +#endif // WIRELESS_FRAME_H + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/ui/qt/wireless_frame.ui b/ui/qt/wireless_frame.ui new file mode 100644 index 0000000000..1aa41d711c --- /dev/null +++ b/ui/qt/wireless_frame.ui @@ -0,0 +1,208 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>WirelessFrame</class> + <widget class="QFrame" name="WirelessFrame"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>955</width> + <height>20</height> + </rect> + </property> + <property name="windowTitle"> + <string>Frame</string> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <property name="topMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QStackedWidget" name="stackedWidget"> + <widget class="QWidget" name="interfacePage"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="topMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="interfaceLabel"> + <property name="text"> + <string>Interface</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="interfaceComboBox"> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToContents</enum> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>12</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="channelLabel"> + <property name="toolTip"> + <string><html><head/><body><p>Set the 802.11 channel.</p></body></html></string> + </property> + <property name="text"> + <string>Channel</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="channelComboBox"> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToContents</enum> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="channelTypeComboBox"> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToContents</enum> + </property> + </widget> + </item> + <item> + <widget class="QFrame" name="fcsFilterFrame"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + <layout class="QHBoxLayout" name="fcsFilterHLayout"> + <property name="topMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>37</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="fcsLabel"> + <property name="toolTip"> + <string><html><head/><body><p>When capturing, show all frames, ones that have a valid frame check sequence (FCS), or ones with an invalid FCS.</p></body></html></string> + </property> + <property name="text"> + <string>FCS Filter</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="fcsComboBox"> + <item> + <property name="text"> + <string>All Frames</string> + </property> + </item> + <item> + <property name="text"> + <string>Valid Frames</string> + </property> + </item> + <item> + <property name="text"> + <string>Invalid Frames</string> + </property> + </item> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="noWirelessPage"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="topMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="noWirelessLabel"> + <property name="text"> + <string>Wireless controls are not supported in this version of Wireshark.</string> + </property> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QToolButton" name="helperToolButton"> + <property name="text"> + <string>External Helper</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="prefsToolButton"> + <property name="toolTip"> + <string><html><head/><body><p>Show the IEEE 802.11 preferences, including decryption keys.</p></body></html></string> + </property> + <property name="text"> + <string>802.11 Preferences</string> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/wireshark-qt.cpp b/wireshark-qt.cpp index f42697c3cf..aa2859bec4 100644 --- a/wireshark-qt.cpp +++ b/wireshark-qt.cpp @@ -119,10 +119,6 @@ capture_options global_capture_opts; #endif -#ifdef HAVE_AIRPCAP -int airpcap_dll_ret_val = -1; -#endif - GString *comp_info_str, *runtime_info_str; /* update the main window */ @@ -438,7 +434,7 @@ int main(int argc, char *argv[]) gboolean arg_error = FALSE; #ifdef _WIN32 - WSADATA wsaData; + WSADATA wsaData; #endif /* _WIN32 */ char *rf_path; @@ -644,6 +640,8 @@ DIAG_ON(cast-qual) #ifdef HAVE_AIRPCAP /* Load the airpcap.dll. This must also be done before collecting * run-time version information. */ + load_airpcap(); +#if 0 airpcap_dll_ret_val = load_airpcap(); switch (airpcap_dll_ret_val) { @@ -664,7 +662,6 @@ DIAG_ON(cast-qual) airpcap_if_active = airpcap_get_default_if(airpcap_if_list); } break; -#if 0 /* * XXX - Maybe we need to warn the user if one of the following happens??? */ @@ -679,8 +676,8 @@ DIAG_ON(cast-qual) case AIRPCAP_DLL_NOT_FOUND: simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n"); break; -#endif } +#endif #endif /* HAVE_AIRPCAP */ #endif /* _WIN32 */ diff --git a/wsutil/CMakeLists.txt b/wsutil/CMakeLists.txt index 6741ce4c8c..d21dac6fb0 100644 --- a/wsutil/CMakeLists.txt +++ b/wsutil/CMakeLists.txt @@ -52,6 +52,7 @@ set(WSUTIL_FILES des.c eax.c filesystem.c + frequency-utils.c g711.c jsmn.c md4.c diff --git a/wsutil/Makefile.common b/wsutil/Makefile.common index 9507e3f146..19626aef34 100644 --- a/wsutil/Makefile.common +++ b/wsutil/Makefile.common @@ -49,6 +49,7 @@ LIBWSUTIL_SRC = \ des.c \ eax.c \ filesystem.c \ + frequency-utils.c \ g711.c \ jsmn.c \ md4.c \ @@ -98,6 +99,7 @@ libwsutil_nonrepl_INCLUDES = \ des.h \ eax.h \ filesystem.h \ + frequency-utils.h \ g711.h \ jsmn.h \ md4.h \ diff --git a/epan/frequency-utils.c b/wsutil/frequency-utils.c index 2ee6bc9d8c..2ee6bc9d8c 100644 --- a/epan/frequency-utils.c +++ b/wsutil/frequency-utils.c diff --git a/epan/frequency-utils.h b/wsutil/frequency-utils.h index 10603e06d7..10603e06d7 100644 --- a/epan/frequency-utils.h +++ b/wsutil/frequency-utils.h |