Attach to all frames containing LEAP messages an indication of the state

of the LEAP negotiation, so we can properly dissect the LEAP message
after the first pass through the packets.

For that to be computed correctly, EAP frames have to be dissected on
the first pass through the capture file, even if the protocol tree isn't
being generated; that means that RADIUS AVPs need to be dissected even
if the protocol tree isn't being generated.

svn path=/trunk/; revision=5004
This commit is contained in:
Guy Harris 2002-03-22 11:41:59 +00:00
parent f970451d95
commit fb18dbe6f5
2 changed files with 177 additions and 107 deletions

View File

@ -2,7 +2,7 @@
* Routines for EAP Extensible Authentication Protocol dissection
* RFC 2284
*
* $Id: packet-eap.c,v 1.19 2002/03/19 20:55:40 guy Exp $
* $Id: packet-eap.c,v 1.20 2002/03/22 11:41:59 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -121,6 +121,29 @@ static const value_string eap_type_vals[] = {
};
/*
* Attach to all frames containing LEAP messages an indication of
* the state of the LEAP negotiation, so we can properly dissect
* the LEAP message after the first pass through the packets.
*/
static GMemChunk *leap_state_chunk = NULL;
typedef struct {
int state;
} leap_state_t;
static void
eap_init_protocol(void)
{
if (leap_state_chunk != NULL)
g_mem_chunk_destroy(leap_state_chunk);
leap_state_chunk = g_mem_chunk_new("leap_state_chunk",
sizeof (leap_state_t),
100 * sizeof (leap_state_t),
G_ALLOC_ONLY);
}
static int
dissect_eap_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
gboolean fragmented)
@ -132,6 +155,7 @@ dissect_eap_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
gint len;
proto_tree *ti;
proto_tree *eap_tree = NULL;
leap_state_t *leap_state_info;
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "EAP");
@ -184,151 +208,194 @@ dissect_eap_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
val_to_str(eap_type, eap_type_vals,
"Unknown type (0x%02X)"));
if (tree) {
if (tree)
proto_tree_add_uint(eap_tree, hf_eap_type, tvb, 4, 1, eap_type);
if (len > 5) {
int offset = 5;
gint size = len - offset;
if (len > 5) {
int offset = 5;
gint size = len - offset;
switch (eap_type) {
switch (eap_type) {
case EAP_TYPE_ID:
case EAP_TYPE_ID:
if (tree) {
proto_tree_add_text(eap_tree, tvb, offset, size,
"Identity (%d byte%s): %s",
size, plurality(size, "", "s"),
tvb_format_text(tvb, offset, size));
leap_state = 0;
break;
}
leap_state = 0;
break;
case EAP_TYPE_NOTIFY:
case EAP_TYPE_NOTIFY:
if (tree) {
proto_tree_add_text(eap_tree, tvb, offset, size,
"Notification (%d byte%s): %s",
size, plurality(size, "", "s"),
tvb_format_text(tvb, offset, size));
break;
}
break;
case EAP_TYPE_NAK:
case EAP_TYPE_NAK:
if (tree) {
proto_tree_add_uint(eap_tree, hf_eap_type_nak, tvb,
offset, size, eap_type);
break;
}
break;
case EAP_TYPE_TLS:
{
guint8 flags = tvb_get_guint8(tvb, offset);
case EAP_TYPE_TLS:
{
guint8 flags = tvb_get_guint8(tvb, offset);
if (tree) {
proto_tree_add_text(eap_tree, tvb, offset, 1, "Flags(%i): %s%s%s",
flags,
flags & 128 ? "Length " : "",
flags & 64 ? "More " : "",
flags & 32 ? "Start " : "");
size--;
offset++;
}
size--;
offset++;
if (flags >> 7) {
guint32 length = tvb_get_ntohl(tvb, offset);
if (flags >> 7) {
guint32 length = tvb_get_ntohl(tvb, offset);
if (tree) {
proto_tree_add_text(eap_tree, tvb, offset, 4, "Length: %i",
length);
size -= 4;
offset += 4;
}
size -= 4;
offset += 4;
}
if (size>0) {
tvbuff_t *next_tvb;
gint tvb_len;
if (size>0) {
tvbuff_t *next_tvb;
gint tvb_len;
tvb_len = tvb_length_remaining(tvb, offset);
if (size < tvb_len)
tvb_len = size;
next_tvb = tvb_new_subset(tvb, offset, tvb_len, size);
call_dissector(ssl_handle, next_tvb, pinfo, eap_tree);
}
}
break;
tvb_len = tvb_length_remaining(tvb, offset);
if (size < tvb_len)
tvb_len = size;
next_tvb = tvb_new_subset(tvb, offset, tvb_len, size);
call_dissector(ssl_handle, next_tvb, pinfo, eap_tree);
}
}
break;
/*
Cisco's LEAP
http://www.missl.cs.umd.edu/wireless/ethereal/leap.txt
*/
/*
Cisco's LEAP
http://www.missl.cs.umd.edu/wireless/ethereal/leap.txt
*/
case EAP_TYPE_LEAP:
{
guint8 field,count,namesize;
case EAP_TYPE_LEAP:
{
guint8 field,count,namesize;
/* Version (byte) */
/* Version (byte) */
if (tree) {
field = tvb_get_guint8(tvb, offset);
proto_tree_add_text(eap_tree, tvb, offset, 1,
"Version: %i",field);
size--;
offset++;
}
size--;
offset++;
/* Unused (byte) */
/* Unused (byte) */
if (tree) {
field = tvb_get_guint8(tvb, offset);
proto_tree_add_text(eap_tree, tvb, offset, 1,
"Reserved: %i",field);
size--;
offset++;
}
size--;
offset++;
/* Count (byte) */
count = tvb_get_guint8(tvb, offset);
/* Count (byte) */
count = tvb_get_guint8(tvb, offset);
if (tree) {
proto_tree_add_text(eap_tree, tvb, offset, 1,
"Count: %i",count);
size--;
offset++;
}
size--;
offset++;
/* Data (byte*Count)
This part is state-dependent. */
if (leap_state==0) {
/* Data (byte*Count)
This part is state-dependent.
See if we've already remembered the state. */
leap_state_info = p_get_proto_data(pinfo->fd, proto_eap);
if (leap_state_info != NULL) {
/* We have - use the remembered state. */
leap_state = leap_state_info->state;
} else {
/* We haven't - remember the state for subsequent accesses. */
leap_state_info = g_mem_chunk_alloc(leap_state_chunk);
leap_state_info->state = leap_state;
p_add_proto_data(pinfo->fd, proto_eap, leap_state_info);
}
if (leap_state==0) {
if (tree) {
proto_tree_add_text(eap_tree, tvb, offset, count,
"Peer Challenge [R8] (%d byte%s) Value:'%s'",
count, plurality(count, "", "s"),
tvb_bytes_to_str(tvb, offset, count));
leap_state++;
} else if (leap_state==1) {
}
leap_state++;
} else if (leap_state==1) {
if (tree) {
proto_tree_add_text(eap_tree, tvb, offset, count,
"Peer Response MSCHAP [24] (%d byte%s) NtChallengeResponse(%s)",
count, plurality(count, "", "s"),
tvb_bytes_to_str(tvb, offset, count));
leap_state++;
} else if (leap_state==2) {
}
leap_state++;
} else if (leap_state==2) {
if (tree) {
proto_tree_add_text(eap_tree, tvb, offset, count,
"AP Challenge [R8] (%d byte%s) Value:'%s'",
count, plurality(count, "", "s"),
tvb_bytes_to_str(tvb, offset, count));
leap_state++;
} else if (leap_state==3) {
}
leap_state++;
} else if (leap_state==3) {
if (tree) {
proto_tree_add_text(eap_tree, tvb, offset, count,
"AP Response [24] (%d byte%s) NtChallengeResponse(%s)",
count, plurality(count, "", "s"),
tvb_bytes_to_str(tvb, offset, count));
leap_state++;
} else
}
leap_state++;
} else {
if (tree) {
proto_tree_add_text(eap_tree, tvb, offset, count,
"Data (%d byte%s): %s",
count, plurality(count, "", "s"),
tvb_bytes_to_str(tvb, offset, count));
}
}
size -= count;
offset += count;
size -= count;
offset += count;
/* Name (Length-(8+Count)) */
namesize = eap_len - (8+count);
/* Name (Length-(8+Count)) */
namesize = eap_len - (8+count);
if (tree) {
proto_tree_add_text(eap_tree, tvb, offset, namesize,
"Name (%d byte%s): %s",
namesize, plurality(count, "", "s"),
tvb_format_text(tvb, offset, namesize));
size -= namesize;
offset += namesize;
}
break;
size -= namesize;
offset += namesize;
}
break;
default:
default:
if (tree) {
proto_tree_add_text(eap_tree, tvb, offset, size,
"Type-Data (%d byte%s) Value: %s",
size, plurality(size, "", "s"),
tvb_bytes_to_str(tvb, offset, size));
break;
}
break;
}
}
}
@ -376,6 +443,7 @@ proto_register_eap(void)
"EAP", "eap");
proto_register_field_array(proto_eap, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
register_init_routine(&eap_init_protocol);
new_register_dissector("eap", dissect_eap, proto_eap);
new_register_dissector("eap_fragment", dissect_eap_fragment, proto_eap);

View File

@ -4,7 +4,7 @@
*
* RFC 2865, RFC 2866, RFC 2867, RFC 2868, RFC 2869
*
* $Id: packet-radius.c,v 1.50 2002/03/22 02:38:52 guy Exp $
* $Id: packet-radius.c,v 1.51 2002/03/22 11:41:59 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -967,8 +967,9 @@ void dissect_attribute_value_pairs(tvbuff_t *tvb, int offset,proto_tree *tree,
if (avplength==0)
{
proto_tree_add_text(tree, tvb,offset,0,"No Attribute Value Pairs Found");
return;
if (tree)
proto_tree_add_text(tree, tvb,offset,0,"No Attribute Value Pairs Found");
return;
}
/*
@ -988,23 +989,28 @@ void dissect_attribute_value_pairs(tvbuff_t *tvb, int offset,proto_tree *tree,
* This AVP is bogus - the length includes the type and length
* fields, so it must be >= 2.
*/
proto_tree_add_text(tree, tvb, offset, avph.avp_length,
"t:%s(%u) l:%u (length not >= 2)",
avptpstrval,avph.avp_type,avph.avp_length);
if (tree) {
proto_tree_add_text(tree, tvb, offset, avph.avp_length,
"t:%s(%u) l:%u (length not >= 2)",
avptpstrval, avph.avp_type, avph.avp_length);
}
break;
}
if (avph.avp_type == RD_TP_EAP_MESSAGE) {
proto_item *ti;
proto_tree *eap_tree;
proto_tree *eap_tree = NULL;
gint tvb_len;
tvbuff_t *next_tvb;
int data_len;
int result;
ti = proto_tree_add_text(tree, tvb,offset,avph.avp_length,"t:%s(%u) l:%u",
avptpstrval,avph.avp_type,avph.avp_length);
eap_tree = proto_item_add_subtree(ti, ett_radius_eap);
if (tree) {
ti = proto_tree_add_text(tree, tvb, offset, avph.avp_length,
"t:%s(%u) l:%u",
avptpstrval, avph.avp_type, avph.avp_length);
eap_tree = proto_item_add_subtree(ti, ett_radius_eap);
}
tvb_len = tvb_length_remaining(tvb, offset+2);
data_len = avph.avp_length-2;
if (data_len < tvb_len)
@ -1014,13 +1020,6 @@ void dissect_attribute_value_pairs(tvbuff_t *tvb, int offset,proto_tree *tree,
/*
* Set the columns non-writable, so that the packet list
* shows this as an RADIUS packet, not as an EAP packet.
*
* XXX - we'll call the EAP dissector only if we're building
* a protocol tree. The EAP dissector currently saves no state,
* and won't be modifying the columns, so that's OK right now,
* but it might call the SSL dissector - if that maintains state
* needed for dissection, we'll have to arrange that AVPs be
* dissected even if we're not building a protocol tree.
*/
col_set_writable(pinfo->cinfo, FALSE);
@ -1039,7 +1038,8 @@ void dissect_attribute_value_pairs(tvbuff_t *tvb, int offset,proto_tree *tree,
/* Are we in the process of reassembling? */
if (reassembled_data != NULL) {
/* Yes - show this as an EAP fragment. */
proto_tree_add_text(eap_tree, next_tvb, 0, -1, "EAP fragment");
if (tree)
proto_tree_add_text(eap_tree, next_tvb, 0, -1, "EAP fragment");
/*
* Do we have all of the data in this fragment?
@ -1109,10 +1109,13 @@ void dissect_attribute_value_pairs(tvbuff_t *tvb, int offset,proto_tree *tree,
}
}
} else {
valstr = rd_value_to_str(&avph, tvb, offset);
proto_tree_add_text(tree, tvb,offset,avph.avp_length,
"t:%s(%u) l:%u, %s",
avptpstrval,avph.avp_type,avph.avp_length,valstr);
if (tree) {
valstr = rd_value_to_str(&avph, tvb, offset);
proto_tree_add_text(tree, tvb, offset, avph.avp_length,
"t:%s(%u) l:%u, %s",
avptpstrval, avph.avp_type, avph.avp_length,
valstr);
}
}
offset = offset+avph.avp_length;
@ -1128,7 +1131,7 @@ void dissect_attribute_value_pairs(tvbuff_t *tvb, int offset,proto_tree *tree,
static void dissect_radius(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
proto_tree *radius_tree,*avptree;
proto_tree *radius_tree = NULL, *avptree = NULL;
proto_item *ti,*avptf;
int rhlength;
int rhcode;
@ -1176,24 +1179,23 @@ static void dissect_radius(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_tree_add_text(radius_tree, tvb, 4,
AUTHENTICATOR_LENGTH,
"Authenticator");
}
hdrlength=RD_HDR_LENGTH+AUTHENTICATOR_LENGTH;
avplength= rhlength -hdrlength;
hdrlength=RD_HDR_LENGTH+AUTHENTICATOR_LENGTH;
avplength= rhlength -hdrlength;
if (avplength > 0) {
/* list the attribute value pairs */
if (avplength > 0) {
/* list the attribute value pairs */
avptf = proto_tree_add_text(radius_tree,
tvb,hdrlength,avplength,
"Attribute value pairs");
avptree = proto_item_add_subtree(avptf, ett_radius_avp);
if (tree)
{
avptf = proto_tree_add_text(radius_tree,
tvb,hdrlength,avplength,
"Attribute value pairs");
avptree = proto_item_add_subtree(avptf, ett_radius_avp);
}
if (avptree !=NULL)
{
dissect_attribute_value_pairs(tvb, hdrlength,
avptree,avplength,pinfo);
}
}
dissect_attribute_value_pairs(tvb, hdrlength, avptree, avplength, pinfo);
}
}
/* registration with the filtering engine */