diff options
Diffstat (limited to 'epan/dissectors/packet-turnchannel.c')
-rw-r--r-- | epan/dissectors/packet-turnchannel.c | 91 |
1 files changed, 49 insertions, 42 deletions
diff --git a/epan/dissectors/packet-turnchannel.c b/epan/dissectors/packet-turnchannel.c index ecca59b186..ff4d4fa4ef 100644 --- a/epan/dissectors/packet-turnchannel.c +++ b/epan/dissectors/packet-turnchannel.c @@ -1,5 +1,5 @@ /* packet-turnchannel.c - * Routines for TURN channel dissection (TURN negociation is handled + * Routines for TURN channel dissection (TURN negotiation is handled * in the STUN2 dissector * Copyright 2008, 8x8 Inc. <petithug@8x8.com> * @@ -22,6 +22,7 @@ * - RFC 5780 * - RFC 5766 * - RFC 6156 + * - RFC 8656 * * Update as necessary. */ @@ -38,20 +39,43 @@ void proto_reg_handoff_turnchannel(void); static heur_dissector_list_t heur_subdissector_list; /* Initialize the protocol and registered fields */ -static int proto_turnchannel = -1; +static int proto_turnchannel; -static int hf_turnchannel_id = -1; -static int hf_turnchannel_len = -1; +static int hf_turnchannel_id; +static int hf_turnchannel_len; #define TURNCHANNEL_HDR_LEN ((guint)4) +#define MS_MULTIPLEX_TURN 0xFF10 /* Initialize the subtree pointers */ -static gint ett_turnchannel = -1; +static gint ett_turnchannel; static dissector_handle_t turnchannel_tcp_handle; static dissector_handle_t turnchannel_udp_handle; +/* + * RFC 5764 defined a demultiplexing scheme to allow TURN is co-exist + * on the same 5-tuple as STUN, DTLS, RTP/RTCP, and ZTLS by rejecting + * previous reserved channel numbers, restricting the channel numbers + * to 0x4000-0x7FFF. RFC 5766 (TURN) did not incorporate the restriction, + * but RFC 8656 did, further restricting the channel numbers to the + * range 0x4000-0x4FFF. + * + * Reject channel numbers outside 0x4000-0x7FFF (except for the special + * MS-TURN multiplex channel number), since no implementation has used + * any value outside that range, and the 0x5000-0x7FFF range is reserved + * in the multiplexing scheme. + */ +static gboolean +test_turnchannel_id(guint16 channel_id) +{ + if ((channel_id & 0x4000) == 0x4000 || channel_id == MS_MULTIPLEX_TURN) + return TRUE; + + return FALSE; +} + static int dissect_turnchannel_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) @@ -72,7 +96,7 @@ dissect_turnchannel_message(tvbuff_t *tvb, packet_info *pinfo, channel_id = tvb_get_ntohs(tvb, 0); data_len = tvb_get_ntohs(tvb, 2); - if ((channel_id < 0x4000) || (channel_id > 0xFFFE)) { + if (!test_turnchannel_id(channel_id)) { return 0; } @@ -92,7 +116,6 @@ dissect_turnchannel_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree_add_uint(turnchannel_tree, hf_turnchannel_id, tvb, 0, 2, channel_id); proto_tree_add_uint(turnchannel_tree, hf_turnchannel_len, tvb, 2, 2, data_len); - if (len > TURNCHANNEL_HDR_LEN) { tvbuff_t *next_tvb; guint reported_len, new_len; @@ -120,6 +143,18 @@ static guint get_turnchannel_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) { + guint16 channel_id; + channel_id = tvb_get_ntohs(tvb, 0); + /* If the channel number is outside the range, either we missed + * a TCP segment or this is STUN, DTLS, RTP, etc. multiplexed on + * the same 5-tuple. Report the length as the rest of the packet + * and dissect_turnchannel_message will reject it, rather than + * using a bogus PDU length and messing up the dissection of + * future TURN packets. + */ + if (!test_turnchannel_id(channel_id)) { + return tvb_reported_length(tvb); + } return (guint)tvb_get_ntohs(tvb, offset+2) + TURNCHANNEL_HDR_LEN; } @@ -131,34 +166,6 @@ dissect_turnchannel_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, voi return tvb_captured_length(tvb); } - -static gboolean -dissect_turnchannel_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) -{ - guint len; - guint16 channel_id; - guint16 data_len; - - len = tvb_captured_length(tvb); - /* First, make sure we have enough data to do the check. */ - if (len < TURNCHANNEL_HDR_LEN) { - return FALSE; - } - - channel_id = tvb_get_ntohs(tvb, 0); - data_len = tvb_get_ntohs(tvb, 2); - - if ((channel_id < 0x4000) || (channel_id > 0xFFFE)) { - return FALSE; - } - - if (len != TURNCHANNEL_HDR_LEN + data_len) { - return FALSE; - } - - return dissect_turnchannel_message(tvb, pinfo, tree, NULL); -} - void proto_register_turnchannel(void) { @@ -179,14 +186,18 @@ proto_register_turnchannel(void) }; /* Register the protocol name and description */ - proto_turnchannel = proto_register_protocol("TURN Channel", - "TURNCHANNEL", "turnchannel"); + proto_turnchannel = proto_register_protocol("TURN Channel", "TURNCHANNEL", "turnchannel"); turnchannel_tcp_handle = register_dissector("turnchannel-tcp", dissect_turnchannel_tcp, proto_turnchannel); turnchannel_udp_handle = register_dissector("turnchannel", dissect_turnchannel_message, proto_turnchannel); /* subdissectors */ - heur_subdissector_list = register_heur_dissector_list("turnchannel", proto_turnchannel); + /* XXX: Nothing actually registers to this list. All dissectors register + * to the heuristic subdissector list for STUN, since the STUN dissector + * doesn't actually call this dissector but uses its own implementation + * of TURN Channel messages. + */ + heur_subdissector_list = register_heur_dissector_list_with_description("turnchannel", "TURN Channel message", proto_turnchannel); /* Required function calls to register the header fields and subtrees used */ proto_register_field_array(proto_turnchannel, hf, array_length(hf)); @@ -208,10 +219,6 @@ proto_reg_handoff_turnchannel(void) */ dissector_add_string("tls.alpn", "stun.turn", turnchannel_tcp_handle); dissector_add_string("dtls.alpn", "stun.turn", turnchannel_udp_handle); - - /* TURN negotiation is handled through STUN2 dissector (packet-stun.c), - so only it should be able to determine if a packet is a TURN packet */ - heur_dissector_add("stun", dissect_turnchannel_heur, "TURN Channel over STUN", "turnchannel_stun", proto_turnchannel, HEURISTIC_ENABLE); } /* |