From 064f4d18dbc2cba6452d69bd354da2ff234b4182 Mon Sep 17 00:00:00 2001 From: Dario Lombardo Date: Mon, 19 Sep 2016 14:40:11 +0200 Subject: eap: dissect eap wlan identity. EAP identities can be of different kind. This change adds a sort of heuristic that dissects the wlan identity in the form of @wlan.mnc.mcc.3gppnetwork.org. A general purpose dissection function, acting as a proxy, has been created to make room for other specific dissections. Bug: 12921 Change-Id: Ic48aee004fa7df5ee4dbeca091ed31616d155890 Reviewed-on: https://code.wireshark.org/review/17796 Petri-Dish: Dario Lombardo Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman --- epan/dissectors/packet-e212.c | 2 +- epan/dissectors/packet-e212.h | 2 + epan/dissectors/packet-eap.c | 143 +++++++++++++++++++++++++++++------------- 3 files changed, 102 insertions(+), 45 deletions(-) (limited to 'epan/dissectors') diff --git a/epan/dissectors/packet-e212.c b/epan/dissectors/packet-e212.c index f8e337be68..4578823afc 100644 --- a/epan/dissectors/packet-e212.c +++ b/epan/dissectors/packet-e212.c @@ -2705,7 +2705,7 @@ static const value_string mcc_mnc_codes[] = { { 0, NULL } }; -static value_string_ext mcc_mnc_codes_ext = VALUE_STRING_EXT_INIT(mcc_mnc_codes); +value_string_ext mcc_mnc_codes_ext = VALUE_STRING_EXT_INIT(mcc_mnc_codes); static int proto_e212 = -1; diff --git a/epan/dissectors/packet-e212.h b/epan/dissectors/packet-e212.h index 8434a9b19f..dc00622252 100644 --- a/epan/dissectors/packet-e212.h +++ b/epan/dissectors/packet-e212.h @@ -29,6 +29,8 @@ extern value_string_ext E212_codes_ext; +extern value_string_ext mcc_mnc_codes_ext; + typedef enum { E212_NONE, E212_LAI, diff --git a/epan/dissectors/packet-eap.c b/epan/dissectors/packet-eap.c index 837bb8cbe4..44ce06cf1a 100644 --- a/epan/dissectors/packet-eap.c +++ b/epan/dissectors/packet-eap.c @@ -23,6 +23,8 @@ #include "config.h" +#include + #include #include #include @@ -32,6 +34,7 @@ #include #include "packet-wps.h" +#include "packet-e212.h" void proto_register_eap(void); void proto_reg_handoff_eap(void); @@ -44,8 +47,10 @@ static int hf_eap_type = -1; static int hf_eap_type_nak = -1; static int hf_eap_identity = -1; -static int hf_eap_identity_prefix = -1; static int hf_eap_identity_actual_len = -1; +static int hf_eap_identity_wlan_prefix = -1; +static int hf_eap_identity_wlan_mcc = -1; +static int hf_eap_identity_wlan_mcc_mnc = -1; static int hf_eap_notification = -1; @@ -184,7 +189,7 @@ static const value_string eap_type_vals[] = { }; value_string_ext eap_type_vals_ext = VALUE_STRING_EXT_INIT(eap_type_vals); -const value_string eap_identity_prefix_vals[] = { +const value_string eap_identity_wlan_prefix_vals[] = { { '0', "EAP-AKA Permanent" }, { '1', "EAP-SIM Permanent" }, { '2', "EAP-AKA Pseudonym" }, @@ -547,6 +552,77 @@ dissect_eap_mschapv2(proto_tree *eap_tree, tvbuff_t *tvb, packet_info *pinfo, in } } +/* Dissect the WLAN identity */ +static gboolean +dissect_eap_identity_wlan(tvbuff_t *tvb, proto_tree* tree, int offset, gint size) +{ + guint mnc = 0; + guint mcc = 0; + guint mcc_mnc = 0; + proto_tree* eap_identity_tree = NULL; + guint8 eap_identity_prefix = 0; + guint8* identity = NULL; + gchar** tokens = NULL; + guint ntokens = 0; + gboolean ret = TRUE; + + identity = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, size, ENC_ASCII); + + tokens = g_strsplit_set(identity, "@.", -1); + + while(tokens[ntokens]) + ntokens++; + + /* The WLAN identity must have the form of + @wlan.mnc.mcc.3gppnetwork.org + If not, we don't have a wlan identity + */ + if (ntokens != 6 || g_ascii_strncasecmp(tokens[1], "wlan", 4) || + g_ascii_strncasecmp(tokens[4], "3gppnetwork", 11) || + g_ascii_strncasecmp(tokens[5], "org", 3)) { + ret = FALSE; + goto end; + } + + /* It is very likely that we have a WLAN identity (EAP-AKA/EAP-SIM) */ + /* Go on with the dissection */ + eap_identity_tree = proto_item_add_subtree(tree, ett_identity); + eap_identity_prefix = tokens[0][0]; + proto_tree_add_uint(eap_identity_tree, hf_eap_identity_wlan_prefix, + tvb, offset, 1, eap_identity_prefix); + + /* guess if we have a 3 bytes mnc by comparing the first bytes with the imsi */ + sscanf(tokens[2] + 3, "%u", &mnc); + sscanf(tokens[3] + 3, "%u", &mcc); + + if (!g_ascii_strncasecmp(tokens[0], tokens[2] + 3, 3)) { + mcc_mnc = 1000 * mcc + mnc; + } else { + mcc_mnc = 1000 * mcc + 10 * mnc; + } + + proto_tree_add_uint(eap_identity_tree, hf_eap_identity_wlan_mcc_mnc, + tvb, offset + (guint)strlen(tokens[0]) + (guint)strlen("@wlan.") + + (guint)strlen("mnc"), (guint)strlen(tokens[2]) - (guint)strlen("mnc"), + mcc_mnc); + + proto_tree_add_uint(eap_identity_tree, hf_eap_identity_wlan_mcc, + tvb, offset + (guint)strlen(tokens[0]) + (guint)strlen("@wlan.") + + (guint)strlen(tokens[2]) + 1 + strlen("mcc"), (guint)strlen(tokens[3]) - + (guint)strlen("mcc"), mcc); +end: + g_strfreev(tokens); + return ret; +} + +static void +dissect_eap_identity(tvbuff_t *tvb, proto_tree* tree, int offset, gint size) +{ + /* Try to dissect as WLAN identity */ + if (dissect_eap_identity_wlan(tvb, tree, offset, size)) + return; +} + static void dissect_eap_sim(proto_tree *eap_tree, tvbuff_t *tvb, int offset, gint size) { @@ -592,7 +668,13 @@ dissect_eap_sim(proto_tree *eap_tree, tvbuff_t *tvb, int offset, gint size) proto_tree_add_item(attr_tree, hf_eap_sim_subtype_length, tvb, aoffset, 1, ENC_BIG_ENDIAN); aoffset += 1; aleft -= 1; - proto_tree_add_item(attr_tree, hf_eap_sim_subtype_value, tvb, aoffset, aleft, ENC_NA); + + if (type == AT_IDENTITY) { + proto_tree_add_item(attr_tree, hf_eap_identity_actual_len, tvb, aoffset, 2, ENC_BIG_ENDIAN); + dissect_eap_identity(tvb, attr_tree, aoffset + 2, tvb_get_ntohs(tvb, aoffset)); + } + else + proto_tree_add_item(attr_tree, hf_eap_sim_subtype_value, tvb, aoffset, aleft, ENC_NA); offset += 4 * length; left -= 4 * length; @@ -645,25 +727,8 @@ dissect_eap_aka(proto_tree *eap_tree, tvbuff_t *tvb, int offset, gint size) aleft -= 1; if (type == AT_IDENTITY) { - guint8 eap_identity_prefix; - const char *eap_identity_prefix_str; - proto_tree_add_item(attr_tree, hf_eap_identity_actual_len, tvb, aoffset, 2, ENC_BIG_ENDIAN); - - /* - * XXX - is the first octet of the identity guaranteed to be a prefix - * in EAP-AKA? - */ - eap_identity_prefix = tvb_get_guint8(tvb, aoffset + 2); - eap_identity_prefix_str = try_val_to_str(eap_identity_prefix, eap_identity_prefix_vals); - if (eap_identity_prefix_str != NULL) { - /* - * XXX - see previous comment. - */ - proto_tree_add_uint(attr_tree, hf_eap_identity_prefix, - tvb, aoffset+2, 1, eap_identity_prefix); - } - proto_tree_add_item(attr_tree, hf_eap_identity, tvb, aoffset + 2, aleft - 2, ENC_ASCII|ENC_NA); + dissect_eap_identity(tvb, attr_tree, aoffset + 2, tvb_get_ntohs(tvb, aoffset)); } else proto_tree_add_item(attr_tree, hf_eap_aka_subtype_value, tvb, aoffset, aleft, ENC_NA); @@ -708,8 +773,6 @@ dissect_eap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) guint8 eap_code; guint16 eap_len; guint8 eap_type; - guint8 eap_identity_prefix; - const char *eap_identity_prefix_str; gint len; conversation_t *conversation = NULL; conv_state_t *conversation_state; @@ -717,7 +780,6 @@ dissect_eap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) int leap_state; proto_tree *ti; proto_tree *eap_tree; - proto_tree *eap_identity_tree; proto_tree *eap_tls_flags_tree; proto_item *eap_type_item; proto_item *eap_identity_item; @@ -839,23 +901,7 @@ dissect_eap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) case EAP_TYPE_ID: if (size > 0) { eap_identity_item = proto_tree_add_item(eap_tree, hf_eap_identity, tvb, offset, size, ENC_ASCII|ENC_NA); - eap_identity_tree = proto_item_add_subtree(eap_identity_item, ett_identity); - /* - * XXX - is there a better way to determine whether the identity - * is something that would actually *have* a prefix? Not all EAP - * is EAP-AKA or EAP-SIM. - */ - eap_identity_prefix = tvb_get_guint8(tvb, offset); - eap_identity_prefix_str = try_val_to_str(eap_identity_prefix, eap_identity_prefix_vals); - if (eap_identity_prefix_str != NULL) { - /* - * XXX - see previous comment; just because the first byte - * of the identity is a value that happens to be a valid - * prefix, that doesn't *ipso facto* mean it *is* a prefix. - */ - proto_tree_add_uint(eap_identity_tree, hf_eap_identity_prefix, - tvb, offset, 1, eap_identity_prefix); - } + dissect_eap_identity(tvb, eap_identity_item, offset, size); } if(!pinfo->fd->flags.visited) { conversation_state->leap_state = 0; @@ -1309,9 +1355,18 @@ proto_register_eap(void) FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, - { &hf_eap_identity_prefix, { - "Identity Prefix", "eap.identity.prefix", - FT_CHAR, BASE_HEX, VALS(eap_identity_prefix_vals), 0x0, NULL, HFILL }}, + { &hf_eap_identity_wlan_prefix, { + "WLAN Identity Prefix", "eap.identity.wlan.prefix", + FT_CHAR, BASE_HEX, VALS(eap_identity_wlan_prefix_vals), 0x0, + NULL, HFILL }}, + + { &hf_eap_identity_wlan_mcc, { + "WLAN Identity Mobile Country Code", "eap.identity.wlan.mcc", + FT_UINT16, BASE_DEC|BASE_EXT_STRING, &E212_codes_ext, 0x0, NULL, HFILL }}, + + { &hf_eap_identity_wlan_mcc_mnc, { + "WLAN Identity Mobile Network Code", "eap.identity.wlan.mnc", + FT_UINT16, BASE_DEC|BASE_EXT_STRING, &mcc_mnc_codes_ext, 0x0, NULL, HFILL }}, { &hf_eap_identity_actual_len, { "Identity Actual Length", "eap.identity.actual_len", -- cgit v1.2.3