From 148f5905afd7e51c8dc15ff202bf40b192f6a924 Mon Sep 17 00:00:00 2001 From: easonweii Date: Wed, 18 May 2022 11:35:52 +0800 Subject: SDP: Minor Refactoring by Extract Method Extract Method for multiple message of SDP Media Attribute to simplify things and Make processes clearer. dissect_sdp_media_attribute_rtpmap dissect_sdp_media_attribute_fmtp dissect_sdp_media_attribute_path dissect_sdp_media_attribute_h248_item dissect_sdp_media_attribute_crypto The original function remain unchanged. --- epan/dissectors/packet-sdp.c | 843 +++++++++++++++++++++++-------------------- 1 file changed, 444 insertions(+), 399 deletions(-) (limited to 'epan/dissectors') diff --git a/epan/dissectors/packet-sdp.c b/epan/dissectors/packet-sdp.c index fb0716e42c..165b4a4b52 100644 --- a/epan/dissectors/packet-sdp.c +++ b/epan/dissectors/packet-sdp.c @@ -1605,31 +1605,454 @@ static const string_string media_format_str_types[] = { { 0, NULL } }; +static void +dissect_sdp_media_attribute_rtpmap(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int length, + transport_info_t *transport_info, session_info_t *session_info, + media_description_t *media_desc, int offset) +{ + gint next_offset, tokenlen; + const guint8 *payload_type; + proto_item *pi; + guint8 pt; + + next_offset = tvb_find_guint8(tvb, offset, -1, ' '); + + if (next_offset == -1) + return; + + tokenlen = next_offset - offset; + + proto_tree_add_item_ret_string(tree, hf_media_format, tvb, + offset, tokenlen, ENC_UTF_8|ENC_NA, pinfo->pool, &payload_type); + + offset = next_offset + 1; + + next_offset = tvb_find_guint8(tvb, offset, -1, '/'); + + if (next_offset == -1) { + return; + } + + tokenlen = next_offset - offset; + + proto_tree_add_item(tree, hf_media_encoding_name, tvb, + offset, tokenlen, ENC_UTF_8); + + if (!ws_strtou8(payload_type, NULL, &pt) || pt >= SDP_NO_OF_PT) { + return; /* Invalid */ + } + + /* String is file scope allocated because transport_info is connection related */ + transport_info->encoding_name[pt] = (char*)tvb_get_string_enc(wmem_file_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); + + next_offset = next_offset + 1; + offset = next_offset; + while (length-1 >= next_offset) { + if (!g_ascii_isdigit(tvb_get_guint8(tvb, next_offset))) + break; + next_offset++; + } + tokenlen = next_offset - offset; + pi = proto_tree_add_item(tree, hf_media_sample_rate, tvb, + offset, tokenlen, ENC_UTF_8); + transport_info->sample_rate[pt] = 0; + if (!ws_strtou32(tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA), + NULL, &transport_info->sample_rate[pt])) { + expert_add_info(pinfo, pi, &ei_sdp_invalid_sample_rate); + } else if (!strcmp(transport_info->encoding_name[pt], "G722")) { + // The reported sampling rate is 8000, but the actual value is + // 16kHz. https://tools.ietf.org/html/rfc3551#section-4.5.2 + proto_item_append_text(pi, " (RTP clock rate is 8kHz, actual sampling rate is 16kHz)"); + } + /* As per RFC2327 it is possible to have multiple Media Descriptions ("m="). + For example: + + a=rtpmap:101 G726-32/8000 + m=audio 49170 RTP/AVP 0 97 + a=rtpmap:97 telephone-event/8000 + m=audio 49172 RTP/AVP 97 101 + a=rtpmap:97 G726-24/8000 + + The Media attributes ("a="s) after the "m=" only apply for that "m=". + If there is an "a=" before the first "m=", that attribute applies for + all the session (all the "m="s). + */ + + if (session_info) { + /* If this "a=" appear before any "m=", we add it to the session + * info, these will be added later to all media (via + * sdp_new_media_description). + */ + rtp_dyn_payload_insert(session_info->rtp_dyn_payload, + pt, + transport_info->encoding_name[pt], + transport_info->sample_rate[pt]); + } else if (media_desc) { + /* if the "a=" is after an "m=", only apply to this "m=" */ + rtp_dyn_payload_insert(media_desc->media.rtp_dyn_payload, + pt, + transport_info->encoding_name[pt], + transport_info->sample_rate[pt]); + } +} + +static void +dissect_sdp_media_attribute_fmtp(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, + transport_info_t *transport_info, int offset) +{ + gint next_offset, tokenlen; + proto_item *fmtp_item, *media_format_item; + const guint8 *payload_type; + const guint8 *media_format_str; + proto_tree *fmtp_tree; + gboolean has_more_pars = TRUE; + /* Reading the Format parameter(fmtp) */ + guint8 media_format; + + if (tree == NULL) { + return; + } + /* Skip leading space, if any */ + offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset)); + /* Media format extends to the next space */ + next_offset = tvb_find_guint8(tvb, offset, -1, ' '); + + if (next_offset == -1) + return; + + tokenlen = next_offset - offset; + + media_format_item = proto_tree_add_item_ret_string(tree, hf_media_format, tvb, + offset, tokenlen, ENC_UTF_8 | ENC_NA, pinfo->pool, &payload_type); + + /* Append encoding name to format if known */ + payload_type = wmem_ascii_strdown(pinfo->pool, payload_type, -1); + media_format = 0; + if ((media_format_str = try_str_to_str(payload_type, media_format_str_types))) { + + proto_item_append_text(media_format_item, " [%s]", + media_format_str); + } else if (ws_strtou8(payload_type, NULL, &media_format) && media_format < SDP_NO_OF_PT) { + if (media_format) { + proto_item_append_text(media_format_item, " [%s]", + transport_info->encoding_name[media_format]); + } + } else { + expert_add_info(pinfo, media_format_item, &ei_sdp_invalid_media_format); + return; + } + + +#if 0 /* XXX: ?? */ + payload_type = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_ASCII); +#endif + /* Move offset past the payload type */ + offset = next_offset + 1; + + while (has_more_pars == TRUE) { + next_offset = tvb_find_guint8(tvb, offset, -1, ';'); + offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset)); + + if (next_offset == -1) { + has_more_pars = FALSE; + next_offset= tvb_captured_length(tvb); + } + + /* There are at least 2 - add the first parameter */ + tokenlen = next_offset - offset; + fmtp_item = proto_tree_add_item(tree, hf_media_format_specific_parameter, tvb, + offset, tokenlen, ENC_UTF_8); + + fmtp_tree = proto_item_add_subtree(fmtp_item, ett_sdp_fmtp); + + decode_sdp_fmtp(fmtp_tree, tvb, pinfo, offset, tokenlen, + transport_info->encoding_name[media_format]); + + /* Move offset past "; " and onto firts char */ + offset = next_offset + 1; + } +} + +static void +dissect_sdp_media_attribute_path(packet_info *pinfo, tvbuff_t *tvb, guint8 *attribute_value, + media_description_t *media_desc, const char *msrp_res, int offset) +{ + /* msrp attributes that contain address needed for conversation */ + /* RFC 4975 + * path = path-label ":" path-list + * path-label = "path" + * path-list= MSRP-URI *(SP MSRP-URI) + * MSRP-URI = msrp-scheme "://" authority + * ["/" session-id] ";" transport *( ";" URI-parameter) + * ; authority as defined in RFC3986 + * + * msrp-scheme = "msrp" / "msrps" + * RFC 3986 + * The authority component is preceded by a double slash ("//") and is terminated by + * the next slash ("/"), question mark ("?"), or number sign ("#") character, or by + * the end of the URI. + */ + + /* Check for "msrp://" */ + if (strncmp((char*)attribute_value, msrp_res, strlen(msrp_res)) == 0 && msrp_handle && + media_desc && media_desc->proto == SDP_PROTO_MSRP) { + int address_offset, port_offset, port_end_offset; + + /* Address starts here */ + address_offset = offset + (int)strlen(msrp_res); + + /* Port is after next ':' */ + port_offset = tvb_find_guint8(tvb, address_offset, -1, ':'); + /* Check if port is present if not skipp */ + if (port_offset!= -1) { + /* Port ends with '/' */ + port_end_offset = tvb_find_guint8(tvb, port_offset, -1, '/'); + if (port_end_offset == -1) { + /* No "/" look for the ";" */ + port_end_offset = tvb_find_guint8(tvb, port_offset, -1, ';'); + } + /* Attempt to convert address */ + guint32 msrp_ipaddr; + guint16 msrp_port_number; + if (str_to_ip((char*)tvb_get_string_enc(pinfo->pool, tvb, address_offset, port_offset-address_offset, ENC_UTF_8|ENC_NA), + &msrp_ipaddr)) { + /* Get port number */ + if (ws_strtou16(tvb_get_string_enc(pinfo->pool, tvb, port_offset + 1, + port_end_offset - port_offset - 1, ENC_UTF_8|ENC_NA), NULL, &msrp_port_number)) { + /* Port and address are usable, store for later use in + * complete_descriptions (overrides the "c=" address). */ + alloc_address_wmem(wmem_file_scope(), &media_desc->media_attr.msrp.ipaddr, AT_IPv4, 4, &msrp_ipaddr); + media_desc->media_attr.msrp.port_number = msrp_port_number; + } + } + } + } +} + +static void +dissect_sdp_media_attribute_h248_item(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, + guint8 *attribute_value, const char *msrp_res) +{ + const char *h324ext_h223lcparm = "h324ext/h223lcparm"; + tvbuff_t *h245_tvb; + + if (strncmp((char*)attribute_value, h324ext_h223lcparm, strlen(msrp_res)) == 0) { + /* A.5.1.3 H.223 Logical channel parameters + * This property indicates the H.245 + * H223LogicalChannelsParameters structure encoded by applying the PER specified in + * ITU-T Rec. X.691. Value encoded as per A.5.1.2. For text encoding the mechanism defined + * in ITU-T Rec. H.248.15 is used. + */ + gint len; + asn1_ctx_t actx; + + len = (gint)strlen(attribute_value); + h245_tvb = ascii_bytes_to_tvb(tvb, pinfo, len, attribute_value); + /* arbitrary maximum length */ + /* should go through a handle, however, the two h245 entry + points are different, one is over tpkt and the other is raw + */ + if (h245_tvb) { + asn1_ctx_init(&actx, ASN1_ENC_PER, TRUE, pinfo); + dissect_h245_H223LogicalChannelParameters(h245_tvb, 0, &actx, + tree,hf_SDPh223LogicalChannelParameters); + } + } +} + +static void +dissect_sdp_media_attribute_crypto(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, + transport_info_t *transport_info, int offset) +{ + /* https://tools.ietf.org/html/rfc4568 + * 9.1. Generic "Crypto" Attribute Grammar + * + * The ABNF grammar for the crypto attribute is defined below: + * + * "a=crypto:" tag 1*WSP crypto-suite 1*WSP key-params + * *(1*WSP session-param) + * + * tag = 1*9DIGIT + * crypto-suite = 1*(ALPHA / DIGIT / "_") + * + * key-params = key-param *(";" key-param) + * key-param = key-method ":" key-info + * key-method = "inline" / key-method-ext + * key-method-ext = 1*(ALPHA / DIGIT / "_") + * key-info = 1*(%x21-3A / %x3C-7E) ; visible (printing) chars + * ; except semi-colon + * session-param = 1*(VCHAR) ; visible (printing) characters + * + * where WSP, ALPHA, DIGIT, and VCHAR are defined in [RFC4234]. + * + */ + gint next_offset, tokenlen; + proto_tree *parameter_item; + proto_item *parameter_tree; + guint32 crypto_tag; + gboolean crypto_tag_valid; + gboolean has_more_pars = TRUE; + guint8 master_key_length = 0, master_salt_length = 0; + gboolean mki_len_valid; + proto_item *pi; + + /* We are at the first colon */ + /* tag */ + tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset); + if (tokenlen == 0) + return; + crypto_tag_valid = ws_strtou32(tvb_get_string_enc(pinfo->pool, tvb, offset, + tokenlen, ENC_UTF_8|ENC_NA), NULL, &crypto_tag); + pi = proto_tree_add_uint(tree, hf_sdp_crypto_tag, tvb, offset, tokenlen, crypto_tag); + if (!crypto_tag_valid) + expert_add_info(pinfo, pi, &ei_sdp_invalid_crypto_tag); + offset = next_offset + 1; + + /* crypto-suite */ + tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset); + if (tokenlen == 0) + return; + parameter_item = proto_tree_add_item(tree, hf_sdp_crypto_crypto_suite, tvb, offset, tokenlen, ENC_UTF_8); + if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_80", tokenlen) == 0) { + + /* XXX This may only work in simple cases */ + if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) { + transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM; + transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1; + /* number of octets used for the Auth Tag in the RTP payload */ + transport_info->auth_tag_len = 10; + } + master_key_length = 16; /* 128 bits = 16 octets */ + master_salt_length = 14; /* 112 bits = 14 octets */ + } else if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_32", tokenlen) == 0) { + /* XXX This may only work in simple cases */ + if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) { + transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM; + transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1; + /* number of octets used for the Auth Tag in the RTP payload */ + transport_info->auth_tag_len = 4; + } + master_key_length = 16; /* 128 bits = 16 octets */ + master_salt_length = 14; /* 112 bits = 14 octets */ + } else if (tvb_strncaseeql(tvb, offset, "F8_128_HMAC_SHA1_80", tokenlen) == 0) { + if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) { + /* XXX This may only work in simple cases */ + transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_F8; + transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1; + /* number of octets used for the Auth Tag in the RTP payload */ + transport_info->auth_tag_len = 10; + } + master_key_length = 16; /* 128 bits = 16 octets */ + master_salt_length = 14; /* 112 bits = 14 octets */ + } + offset = next_offset + 1; + + /* key-params */ + while (has_more_pars == TRUE) { + int param_end_offset; + tvbuff_t *key_salt_tvb; + gchar *data_p = NULL; + + param_end_offset = tvb_find_guint8(tvb, offset, -1, ';'); + if (param_end_offset == -1) { + has_more_pars = FALSE; + param_end_offset = tvb_captured_length(tvb); + } + /* key-method or key-method-ext */ + next_offset = tvb_find_guint8(tvb, offset, -1, ':'); + if (next_offset == -1) { + expert_add_info(pinfo, parameter_item, &ei_sdp_invalid_key_param); + break; + } + + if (tvb_strncaseeql(tvb, offset, "inline", next_offset-offset) == 0) { + parameter_tree = proto_tree_add_subtree(tree, tvb, offset,param_end_offset-offset, + ett_sdp_crypto_key_parameters, NULL, "Key parameters"); + /* XXX only for SRTP? */ + /* srtp-key-info = key-salt ["|" lifetime] ["|" mki] */ + offset = next_offset +1; + next_offset = tvb_find_guint8(tvb, offset, -1, '|'); + if (next_offset == -1) { + tokenlen = param_end_offset - offset; + } else { + tokenlen = next_offset - offset; + } + data_p = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); + key_salt_tvb = base64_to_tvb(tvb, data_p); + add_new_data_source(pinfo, key_salt_tvb, "Key_Salt_tvb"); + if (master_key_length != 0) { + proto_tree_add_item(parameter_tree, hf_sdp_key_and_salt, tvb, offset, tokenlen, ENC_NA); + proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_key, + key_salt_tvb, 0, master_key_length, ENC_NA); + proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_salt, + key_salt_tvb, master_key_length, master_salt_length, ENC_NA); + } else { + proto_tree_add_item(parameter_tree, hf_sdp_key_and_salt, key_salt_tvb, 0, -1, ENC_NA); + } + + /* ["|" lifetime] ["|" mki] are optional */ + if (next_offset != -1) { + offset = next_offset + 1; + next_offset = tvb_find_guint8(tvb, offset, -1, '|'); + if (next_offset == -1) { + if (next_offset < param_end_offset){ + next_offset = param_end_offset; + } + } + if (next_offset != -1) { + /*lifetime = ["2^"] 1*(DIGIT) ; see section 6.1 for "2^" */ + tokenlen = next_offset - offset; + proto_tree_add_item(parameter_tree, hf_sdp_crypto_lifetime, + tvb, offset, tokenlen, ENC_UTF_8); + offset = next_offset + 1; + } + /* mki = mki-value ":" mki-length + * + * mki-value = 1*DIGIT + */ + if (offset>param_end_offset) { + next_offset = -1; + } else { + next_offset = tvb_find_guint8(tvb, offset, -1, ':'); + } + if (next_offset != -1) { + tokenlen = next_offset - offset; + proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki, tvb, offset, tokenlen, ENC_UTF_8); + offset = next_offset + 1; + + /* mki-length = 1*3DIGIT ; range 1..128. */ + next_offset = param_end_offset; + tokenlen = next_offset - offset; + + /* This will not work if more than one parameter */ + /* number of octets used for the MKI in the RTP payload */ + mki_len_valid = ws_strtou32(tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, + ENC_UTF_8|ENC_NA), NULL, &transport_info->mki_len); + pi = proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki_length, + tvb, offset, tokenlen, ENC_UTF_8); + if (!mki_len_valid) + expert_add_info(pinfo, pi, &ei_sdp_invalid_crypto_mki_length); + } + } + offset = param_end_offset; + } else { + break; + } + } +} + static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_item * ti, int length, transport_info_t *transport_info, session_info_t *session_info, media_description_t *media_desc, sdp_data_t *sdp_data) { - proto_tree *sdp_media_attribute_tree, *parameter_item; - proto_item *fmtp_item, *media_format_item, *parameter_tree; - proto_tree *fmtp_tree; + proto_tree *sdp_media_attribute_tree; proto_item *pi; - gint offset, next_offset, tokenlen, colon_offset; - /*??guint8 *field_name;*/ - const guint8 *payload_type; - const guint8 *media_format_str; + gint offset, tokenlen, colon_offset; guint8 *attribute_value; - guint8 pt; gint sdp_media_attrbute_code; const char *msrp_res = "msrp://"; - const char *h324ext_h223lcparm = "h324ext/h223lcparm"; - gboolean has_more_pars = TRUE; - tvbuff_t *h245_tvb; - guint8 master_key_length = 0, master_salt_length = 0; - guint32 crypto_tag; - gboolean crypto_tag_valid; - gboolean mki_len_valid; offset = 0; @@ -1670,399 +2093,21 @@ static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto switch (sdp_media_attrbute_code) { case SDP_RTPMAP: /* decode the rtpmap to see if it is DynamicPayload to dissect them automatic */ - next_offset = tvb_find_guint8(tvb, offset, -1, ' '); - - if (next_offset == -1) - return; - - tokenlen = next_offset - offset; - - proto_tree_add_item_ret_string(sdp_media_attribute_tree, hf_media_format, tvb, - offset, tokenlen, ENC_UTF_8|ENC_NA, pinfo->pool, &payload_type); - - offset = next_offset + 1; - - next_offset = tvb_find_guint8(tvb, offset, -1, '/'); - - if (next_offset == -1) { - return; - } - - tokenlen = next_offset - offset; - - proto_tree_add_item(sdp_media_attribute_tree, hf_media_encoding_name, tvb, - offset, tokenlen, ENC_UTF_8); - - if (!ws_strtou8(payload_type, NULL, &pt) || pt >= SDP_NO_OF_PT) { - return; /* Invalid */ - } - - /* String is file scope allocated because transport_info is connection related */ - transport_info->encoding_name[pt] = (char*)tvb_get_string_enc(wmem_file_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); - - next_offset = next_offset + 1; - offset = next_offset; - while (length-1 >= next_offset) { - if (!g_ascii_isdigit(tvb_get_guint8(tvb, next_offset))) - break; - next_offset++; - } - tokenlen = next_offset - offset; - pi = proto_tree_add_item(sdp_media_attribute_tree, hf_media_sample_rate, tvb, - offset, tokenlen, ENC_UTF_8); - transport_info->sample_rate[pt] = 0; - if (!ws_strtou32(tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA), - NULL, &transport_info->sample_rate[pt])) { - expert_add_info(pinfo, pi, &ei_sdp_invalid_sample_rate); - } else if (!strcmp(transport_info->encoding_name[pt], "G722")) { - // The reported sampling rate is 8000, but the actual value is - // 16kHz. https://tools.ietf.org/html/rfc3551#section-4.5.2 - proto_item_append_text(pi, " (RTP clock rate is 8kHz, actual sampling rate is 16kHz)"); - } - /* As per RFC2327 it is possible to have multiple Media Descriptions ("m="). - For example: - - a=rtpmap:101 G726-32/8000 - m=audio 49170 RTP/AVP 0 97 - a=rtpmap:97 telephone-event/8000 - m=audio 49172 RTP/AVP 97 101 - a=rtpmap:97 G726-24/8000 - - The Media attributes ("a="s) after the "m=" only apply for that "m=". - If there is an "a=" before the first "m=", that attribute applies for - all the session (all the "m="s). - */ - - if (session_info) { - /* If this "a=" appear before any "m=", we add it to the session - * info, these will be added later to all media (via - * sdp_new_media_description). - */ - rtp_dyn_payload_insert(session_info->rtp_dyn_payload, - pt, - transport_info->encoding_name[pt], - transport_info->sample_rate[pt]); - } else if (media_desc) { - /* if the "a=" is after an "m=", only apply to this "m=" */ - rtp_dyn_payload_insert(media_desc->media.rtp_dyn_payload, - pt, - transport_info->encoding_name[pt], - transport_info->sample_rate[pt]); - } + dissect_sdp_media_attribute_rtpmap(sdp_media_attribute_tree, pinfo, tvb, length, transport_info, + session_info, media_desc, offset); break; case SDP_FMTP: - if (sdp_media_attribute_tree) { - guint8 media_format; - /* Reading the Format parameter(fmtp) */ - /* Skip leading space, if any */ - offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset)); - /* Media format extends to the next space */ - next_offset = tvb_find_guint8(tvb, offset, -1, ' '); - - if (next_offset == -1) - return; - - tokenlen = next_offset - offset; - - media_format_item = proto_tree_add_item_ret_string(sdp_media_attribute_tree, hf_media_format, tvb, - offset, tokenlen, ENC_UTF_8 | ENC_NA, pinfo->pool, &payload_type); - - /* Append encoding name to format if known */ - payload_type = wmem_ascii_strdown(pinfo->pool, payload_type, -1); - media_format = 0; - if ((media_format_str = try_str_to_str(payload_type, media_format_str_types))) { - - proto_item_append_text(media_format_item, " [%s]", - media_format_str); - } else if (ws_strtou8(payload_type, NULL, &media_format) && media_format < SDP_NO_OF_PT) { - if (media_format) { - proto_item_append_text(media_format_item, " [%s]", - transport_info->encoding_name[media_format]); - } - } else { - expert_add_info(pinfo, media_format_item, &ei_sdp_invalid_media_format); - return; - } - - -#if 0 /* XXX: ?? */ - payload_type = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_ASCII); -#endif - /* Move offset past the payload type */ - offset = next_offset + 1; - - while (has_more_pars == TRUE) { - next_offset = tvb_find_guint8(tvb, offset, -1, ';'); - offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset)); - - if (next_offset == -1) { - has_more_pars = FALSE; - next_offset= tvb_captured_length(tvb); - } - - /* There are at least 2 - add the first parameter */ - tokenlen = next_offset - offset; - fmtp_item = proto_tree_add_item(sdp_media_attribute_tree, - hf_media_format_specific_parameter, tvb, - offset, tokenlen, ENC_UTF_8); - - fmtp_tree = proto_item_add_subtree(fmtp_item, ett_sdp_fmtp); - - decode_sdp_fmtp(fmtp_tree, tvb, pinfo, offset, tokenlen, - transport_info->encoding_name[media_format]); - - /* Move offset past "; " and onto firts char */ - offset = next_offset + 1; - } - } + dissect_sdp_media_attribute_fmtp(sdp_media_attribute_tree, pinfo, tvb, transport_info, offset); break; case SDP_PATH: - /* msrp attributes that contain address needed for conversation */ - /* RFC 4975 - * path = path-label ":" path-list - * path-label = "path" - * path-list= MSRP-URI *(SP MSRP-URI) - * MSRP-URI = msrp-scheme "://" authority - * ["/" session-id] ";" transport *( ";" URI-parameter) - * ; authority as defined in RFC3986 - * - * msrp-scheme = "msrp" / "msrps" - * RFC 3986 - * The authority component is preceded by a double slash ("//") and is terminated by - * the next slash ("/"), question mark ("?"), or number sign ("#") character, or by - * the end of the URI. - */ - - /* Check for "msrp://" */ - if (strncmp((char*)attribute_value, msrp_res, strlen(msrp_res)) == 0 && msrp_handle && - media_desc && media_desc->proto == SDP_PROTO_MSRP) { - int address_offset, port_offset, port_end_offset; - - /* Address starts here */ - address_offset = offset + (int)strlen(msrp_res); - - /* Port is after next ':' */ - port_offset = tvb_find_guint8(tvb, address_offset, -1, ':'); - /* Check if port is present if not skipp */ - if (port_offset!= -1) { - /* Port ends with '/' */ - port_end_offset = tvb_find_guint8(tvb, port_offset, -1, '/'); - if (port_end_offset == -1) { - /* No "/" look for the ";" */ - port_end_offset = tvb_find_guint8(tvb, port_offset, -1, ';'); - } - /* Attempt to convert address */ - guint32 msrp_ipaddr; - guint16 msrp_port_number; - if (str_to_ip((char*)tvb_get_string_enc(pinfo->pool, tvb, address_offset, port_offset-address_offset, ENC_UTF_8|ENC_NA), - &msrp_ipaddr)) { - /* Get port number */ - if (ws_strtou16(tvb_get_string_enc(pinfo->pool, tvb, port_offset + 1, - port_end_offset - port_offset - 1, ENC_UTF_8|ENC_NA), NULL, &msrp_port_number)) { - /* Port and address are usable, store for later use in - * complete_descriptions (overrides the "c=" address). */ - alloc_address_wmem(wmem_file_scope(), &media_desc->media_attr.msrp.ipaddr, AT_IPv4, 4, &msrp_ipaddr); - media_desc->media_attr.msrp.port_number = msrp_port_number; - } - } - } - } + dissect_sdp_media_attribute_path(pinfo, tvb, attribute_value, media_desc, msrp_res, offset); break; case SDP_H248_ITEM: /* Decode h248 item ITU-T Rec. H.248.12 (2001)/Amd.1 (11/2002)*/ - if (strncmp((char*)attribute_value, h324ext_h223lcparm, strlen(msrp_res)) == 0) { - /* A.5.1.3 H.223 Logical channel parameters - * This property indicates the H.245 - * H223LogicalChannelsParameters structure encoded by applying the PER specified in - * ITU-T Rec. X.691. Value encoded as per A.5.1.2. For text encoding the mechanism defined - * in ITU-T Rec. H.248.15 is used. - */ - gint len; - asn1_ctx_t actx; - - len = (gint)strlen(attribute_value); - h245_tvb = ascii_bytes_to_tvb(tvb, pinfo, len, attribute_value); - /* arbitrary maximum length */ - /* should go through a handle, however, the two h245 entry - points are different, one is over tpkt and the other is raw - */ - if (h245_tvb) { - asn1_ctx_init(&actx, ASN1_ENC_PER, TRUE, pinfo); - dissect_h245_H223LogicalChannelParameters(h245_tvb, 0, &actx, - sdp_media_attribute_tree, - hf_SDPh223LogicalChannelParameters); - } - } + dissect_sdp_media_attribute_h248_item(sdp_media_attribute_tree, pinfo, tvb, attribute_value, msrp_res); break; case SDP_CRYPTO: - /* https://tools.ietf.org/html/rfc4568 - * 9.1. Generic "Crypto" Attribute Grammar - * - * The ABNF grammar for the crypto attribute is defined below: - * - * "a=crypto:" tag 1*WSP crypto-suite 1*WSP key-params - * *(1*WSP session-param) - * - * tag = 1*9DIGIT - * crypto-suite = 1*(ALPHA / DIGIT / "_") - * - * key-params = key-param *(";" key-param) - * key-param = key-method ":" key-info - * key-method = "inline" / key-method-ext - * key-method-ext = 1*(ALPHA / DIGIT / "_") - * key-info = 1*(%x21-3A / %x3C-7E) ; visible (printing) chars - * ; except semi-colon - * session-param = 1*(VCHAR) ; visible (printing) characters - * - * where WSP, ALPHA, DIGIT, and VCHAR are defined in [RFC4234]. - * - */ - - /* We are at the first colon */ - /* tag */ - tokenlen = find_next_token_in_line(tvb, sdp_media_attribute_tree, &offset, &next_offset); - if (tokenlen == 0) - return; - crypto_tag_valid = ws_strtou32(tvb_get_string_enc(pinfo->pool, tvb, offset, - tokenlen, ENC_UTF_8|ENC_NA), NULL, &crypto_tag); - pi = proto_tree_add_uint(sdp_media_attribute_tree, hf_sdp_crypto_tag, tvb, offset, tokenlen, - crypto_tag); - if (!crypto_tag_valid) - expert_add_info(pinfo, pi, &ei_sdp_invalid_crypto_tag); - offset = next_offset + 1; - - /* crypto-suite */ - tokenlen = find_next_token_in_line(tvb, sdp_media_attribute_tree, &offset, &next_offset); - if (tokenlen == 0) - return; - parameter_item = proto_tree_add_item(sdp_media_attribute_tree, hf_sdp_crypto_crypto_suite, - tvb, offset, tokenlen, ENC_UTF_8); - if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_80", tokenlen) == 0) { - - /* XXX This may only work in simple cases */ - if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) { - transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM; - transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1; - /* number of octets used for the Auth Tag in the RTP payload */ - transport_info->auth_tag_len = 10; - } - master_key_length = 16; /* 128 bits = 16 octets */ - master_salt_length = 14; /* 112 bits = 14 octets */ - } else if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_32", tokenlen) == 0) { - /* XXX This may only work in simple cases */ - if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) { - transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM; - transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1; - /* number of octets used for the Auth Tag in the RTP payload */ - transport_info->auth_tag_len = 4; - } - master_key_length = 16; /* 128 bits = 16 octets */ - master_salt_length = 14; /* 112 bits = 14 octets */ - } else if (tvb_strncaseeql(tvb, offset, "F8_128_HMAC_SHA1_80", tokenlen) == 0) { - if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) { - /* XXX This may only work in simple cases */ - transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_F8; - transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1; - /* number of octets used for the Auth Tag in the RTP payload */ - transport_info->auth_tag_len = 10; - } - master_key_length = 16; /* 128 bits = 16 octets */ - master_salt_length = 14; /* 112 bits = 14 octets */ - } - offset = next_offset + 1; - - /* key-params */ - while (has_more_pars == TRUE) { - int param_end_offset; - tvbuff_t *key_salt_tvb; - gchar *data_p = NULL; - - param_end_offset = tvb_find_guint8(tvb, offset, -1, ';'); - if (param_end_offset == -1) { - has_more_pars = FALSE; - param_end_offset = tvb_captured_length(tvb); - } - /* key-method or key-method-ext */ - next_offset = tvb_find_guint8(tvb, offset, -1, ':'); - if (next_offset == -1) { - expert_add_info(pinfo, parameter_item, &ei_sdp_invalid_key_param); - break; - } - - if (tvb_strncaseeql(tvb, offset, "inline", next_offset-offset) == 0) { - parameter_tree = proto_tree_add_subtree(sdp_media_attribute_tree, tvb, offset, - param_end_offset-offset, ett_sdp_crypto_key_parameters, NULL, "Key parameters"); - /* XXX only for SRTP? */ - /* srtp-key-info = key-salt ["|" lifetime] ["|" mki] */ - offset = next_offset +1; - next_offset = tvb_find_guint8(tvb, offset, -1, '|'); - if (next_offset == -1) { - tokenlen = param_end_offset - offset; - } else { - tokenlen = next_offset - offset; - } - data_p = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); - key_salt_tvb = base64_to_tvb(tvb, data_p); - add_new_data_source(pinfo, key_salt_tvb, "Key_Salt_tvb"); - if (master_key_length != 0) { - proto_tree_add_item(parameter_tree, hf_sdp_key_and_salt, tvb, offset, tokenlen, ENC_NA); - proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_key, - key_salt_tvb, 0, master_key_length, ENC_NA); - proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_salt, - key_salt_tvb, master_key_length, master_salt_length, ENC_NA); - } else { - proto_tree_add_item(parameter_tree, hf_sdp_key_and_salt, key_salt_tvb, 0, -1, ENC_NA); - } - - /* ["|" lifetime] ["|" mki] are optional */ - if (next_offset != -1) { - offset = next_offset + 1; - next_offset = tvb_find_guint8(tvb, offset, -1, '|'); - if (next_offset == -1) { - if (next_offset < param_end_offset){ - next_offset = param_end_offset; - } - } - if (next_offset != -1) { - /*lifetime = ["2^"] 1*(DIGIT) ; see section 6.1 for "2^" */ - tokenlen = next_offset - offset; - proto_tree_add_item(parameter_tree, hf_sdp_crypto_lifetime, - tvb, offset, tokenlen, ENC_UTF_8); - offset = next_offset + 1; - } - /* mki = mki-value ":" mki-length - * - * mki-value = 1*DIGIT - */ - if (offset>param_end_offset) { - next_offset = -1; - } else { - next_offset = tvb_find_guint8(tvb, offset, -1, ':'); - } - if (next_offset != -1) { - tokenlen = next_offset - offset; - proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki, tvb, offset, tokenlen, ENC_UTF_8); - offset = next_offset + 1; - - /* mki-length = 1*3DIGIT ; range 1..128. */ - next_offset = param_end_offset; - tokenlen = next_offset - offset; - - /* This will not work if more than one parameter */ - /* number of octets used for the MKI in the RTP payload */ - mki_len_valid = ws_strtou32(tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, - ENC_UTF_8|ENC_NA), NULL, &transport_info->mki_len); - pi = proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki_length, - tvb, offset, tokenlen, ENC_UTF_8); - if (!mki_len_valid) - expert_add_info(pinfo, pi, &ei_sdp_invalid_crypto_mki_length); - } - } - offset = param_end_offset; - } else { - break; - } - } + dissect_sdp_media_attribute_crypto(sdp_media_attribute_tree, pinfo, tvb, transport_info, offset); break; case SDP_CANDIDATE: dissect_sdp_media_attribute_candidate(sdp_media_attribute_tree, pinfo, tvb, offset); -- cgit v1.2.3