based on a patch from Martin Mathieson:

- dissection of SIP headers containing credentials and challenges.

from me:
- add filter fields for some missing related parameters from RFC 3261
- improve calculation of parameter length.

This implements enhancement request (bug id 812)

svn path=/trunk/; revision=17660
This commit is contained in:
Lars Roland 2006-03-18 03:23:26 +00:00
parent a0db53ba73
commit fc81794dc9
1 changed files with 250 additions and 5 deletions

View File

@ -88,6 +88,20 @@ static gint hf_sip_contact_item = -1;
static gint hf_sip_resend = -1;
static gint hf_sip_original_frame = -1;
static gint hf_sip_auth_scheme = -1;
static gint hf_sip_auth_digest_response = -1;
static gint hf_sip_auth_nc = -1;
static gint hf_sip_auth_username = -1;
static gint hf_sip_auth_realm = -1;
static gint hf_sip_auth_nonce = -1;
static gint hf_sip_auth_algorithm = -1;
static gint hf_sip_auth_opaque = -1;
static gint hf_sip_auth_qop = -1;
static gint hf_sip_auth_cnonce = -1;
static gint hf_sip_auth_uri = -1;
static gint hf_sip_auth_domain = -1;
static gint hf_sip_auth_stale = -1;
/* Initialize the subtree pointers */
static gint ett_sip = -1;
static gint ett_sip_reqresp = -1;
@ -393,6 +407,28 @@ static gint hf_header_array[] = {
};
/* Track associations between parameter name and hf item */
typedef struct {
const char *param_name;
const gint *hf_item;
} auth_parameter_t;
static auth_parameter_t auth_parameters_hf_array[] =
{
{"response", &hf_sip_auth_digest_response},
{"nc", &hf_sip_auth_nc},
{"username", &hf_sip_auth_username},
{"realm", &hf_sip_auth_realm},
{"nonce", &hf_sip_auth_nonce},
{"algorithm", &hf_sip_auth_algorithm},
{"opaque", &hf_sip_auth_opaque},
{"qop", &hf_sip_auth_qop},
{"cnonce", &hf_sip_auth_cnonce},
{"uri", &hf_sip_auth_uri},
{"domain", &hf_sip_auth_domain},
{"stale", &hf_sip_auth_stale},
};
/*
* Type of line. It's either a SIP Request-Line, a SIP Status-Line, or
* another type of line.
@ -841,6 +877,7 @@ static gint
dissect_sip_contact_item(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint start_offset, gint line_end_offset)
{
gchar c;
gint i;
proto_item *ti = NULL;
proto_tree *contact_item_tree = NULL, *uri_tree = NULL;
@ -893,13 +930,16 @@ dissect_sip_contact_item(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gi
queried_offset = tvb_find_guint8(tvb, current_offset + 1, line_end_offset - (current_offset + 1), '"');
if(queried_offset == -1)
{
/* malformed URI */
/* malformed Contact header */
return -1;
}
current_offset = queried_offset;
/* Is it escaped? */
} while (tvb_get_guint8(tvb, queried_offset - 1) == '\\');
/* Is it escaped?
* Look for uneven number of backslashes before '"' */
for(i=0;tvb_get_guint8(tvb, queried_offset - (i+1) ) == '\\';i++);
i=i%2;
} while (i == 1);
}
if(c == ',')
@ -949,6 +989,105 @@ dissect_sip_contact_item(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gi
return current_offset;
}
/* Code to parse an authorization header item
* Returns offset at end of parsing, or -1 for unsuccessful parsing
*/
static gint
dissect_sip_authorization_item(tvbuff_t *tvb, proto_tree *tree, gint start_offset, gint line_end_offset)
{
gchar c;
gint current_offset;
gint equals_offset = 0;
gchar *name;
auth_parameter_t *auth_parameter;
guint i = 0;
gboolean in_quoted_string = FALSE;
/* skip Spaces and Tabs */
start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
if (start_offset >= line_end_offset)
{
/* Nothing to parse */
return -1;
}
current_offset = start_offset;
/* Now look for the end of the parameter */
while (current_offset < line_end_offset)
{
c = tvb_get_guint8(tvb, current_offset);
if (c == '=')
{
equals_offset = current_offset;
}
if(c == '"')
{
/* look for the next unescaped '"' */
do
{
current_offset = tvb_find_guint8(tvb, current_offset + 1, line_end_offset - (current_offset + 1), '"');
if(current_offset == -1)
{
/* malformed parameter */
return -1;
}
/* Is it escaped?
* Look for uneven number of backslashes before '"' */
for(i=0;tvb_get_guint8(tvb, current_offset - (i+1) ) == '\\';i++);
i=i%2;
} while (i == 1);
current_offset++;
current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
continue;
}
if (c == ',')
{
break;
}
current_offset++;
}
if (equals_offset == 0)
{
/* Give up if equals not found */
return -1;
}
/* Extract the parameter name */
name = tvb_get_ephemeral_string(tvb, start_offset, equals_offset-start_offset);
/* Try to add parameter as a filterable item */
for (auth_parameter = &auth_parameters_hf_array[i];
i < array_length(auth_parameters_hf_array);
i++, auth_parameter++)
{
if (strcmp(name, auth_parameter->param_name) == 0)
{
proto_tree_add_item(tree, *(auth_parameter->hf_item), tvb,
equals_offset+1, current_offset-equals_offset-1,
FALSE);
break;
}
}
/* If not matched, just add as text... */
if (i == array_length(auth_parameters_hf_array))
{
proto_tree_add_text(tree, tvb, start_offset, current_offset-start_offset,
tvb_get_ephemeral_string(tvb, start_offset,
current_offset-start_offset));
}
return current_offset;
}
/* Code to actually dissect the packets */
static int
dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
@ -1640,6 +1779,46 @@ separator_found2:
comma_offset++; /* skip comma */
}
break;
case POS_AUTHORIZATION:
case POS_WWW_AUTHENTICATE:
case POS_PROXY_AUTHENTICATE:
case POS_PROXY_AUTHORIZATION:
/* Add tree using whole text of line */
if (hdr_tree) {
sip_element_item = proto_tree_add_string_format(hdr_tree,
hf_header_array[hf_index], tvb,
offset, next_offset - offset,
value, "%s",
tvb_format_text(tvb, offset, linelen));
sip_element_tree = proto_item_add_subtree( sip_element_item,
ett_sip_element);
}
/* Parse each individual parameter in the line */
/* skip Spaces and Tabs */
value_offset = tvb_skip_wsp(tvb, value_offset, line_end_offset - value_offset);
comma_offset = tvb_pbrk_guint8(tvb, value_offset, line_end_offset - value_offset, " \t\r\n");
proto_tree_add_item(sip_element_tree, hf_sip_auth_scheme,
tvb, value_offset, comma_offset - value_offset,
FALSE);
while ((comma_offset = dissect_sip_authorization_item(tvb, sip_element_tree, comma_offset, line_end_offset)) != -1)
{
if(comma_offset == line_end_offset)
{
/* Line End reached: Stop Parsing */
break;
}
if(tvb_get_guint8(tvb, comma_offset) != ',')
{
/* Undefined value reached: Stop Parsing */
break;
}
comma_offset++; /* skip comma */
}
break;
default :
if(hdr_tree) {
@ -2689,8 +2868,74 @@ void proto_register_sip(void)
{ &hf_sip_original_frame,
{ "Suspected resend of frame", "sip.resend-original",
FT_FRAMENUM, BASE_NONE, NULL, 0x0,
"Original transmission of frame", HFILL}}
};
"Original transmission of frame", HFILL}
},
{ &hf_sip_auth_scheme,
{ "Authentication Scheme", "sip.auth.scheme",
FT_STRING, BASE_NONE, NULL, 0x0,
"SIP Authentication Scheme", HFILL}
},
{ &hf_sip_auth_digest_response,
{ "Digest Authentication Response", "sip.auth.digest.response",
FT_STRING, BASE_NONE, NULL, 0x0,
"SIP Digest Authentication Response Value ", HFILL}
},
{ &hf_sip_auth_nc,
{ "Nonce Count", "sip.auth.nc",
FT_STRING, BASE_NONE, NULL, 0x0,
"SIP Authentication nonce count", HFILL}
},
{ &hf_sip_auth_username,
{ "Username", "sip.auth.username",
FT_STRING, BASE_NONE, NULL, 0x0,
"Sip authentication username", HFILL}
},
{ &hf_sip_auth_realm,
{ "Realm", "sip.auth.realm",
FT_STRING, BASE_NONE, NULL, 0x0,
"Sip Authentication realm", HFILL}
},
{ &hf_sip_auth_nonce,
{ "Nonce Value", "sip.auth.nonce",
FT_STRING, BASE_NONE, NULL, 0x0,
"SIP Authentication nonce value", HFILL}
},
{ &hf_sip_auth_algorithm,
{ "Algorithm", "sip.auth.algorithm",
FT_STRING, BASE_NONE, NULL, 0x0,
"SIP Authentication Algorithm", HFILL}
},
{ &hf_sip_auth_opaque,
{ "Opaque Value", "sip.auth.opaque",
FT_STRING, BASE_NONE, NULL, 0x0,
"SIP Authentication opaque value", HFILL}
},
{ &hf_sip_auth_qop,
{ "QOP", "sip.auth.qop",
FT_STRING, BASE_NONE, NULL, 0x0,
"SIP Authentication QOP", HFILL}
},
{ &hf_sip_auth_cnonce,
{ "CNonce Value", "sip.auth.cnonce",
FT_STRING, BASE_NONE, NULL, 0x0,
"SIP Authentication Client Nonce value ", HFILL}
},
{ &hf_sip_auth_uri,
{ "Authentication URI", "sip.auth.uri",
FT_STRING, BASE_NONE, NULL, 0x0,
"SIP Authentication URI", HFILL}
},
{ &hf_sip_auth_domain,
{ "Authentication Domain", "sip.auth.domain",
FT_STRING, BASE_NONE, NULL, 0x0,
"SIP Authentication Domain", HFILL}
},
{ &hf_sip_auth_stale,
{ "Stale Flag", "sip.auth.stale",
FT_STRING, BASE_NONE, NULL, 0x0,
"SIP Authentication Stale Flag", HFILL}
}};
/* Setup protocol subtree array */
static gint *ett[] = {