Coverage Report

Created: 2026-09-28 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-stun.c
Line
Count
Source
1
/* packet-stun.c
2
 * Routines for Session Traversal Utilities for NAT (STUN) dissection
3
 * Copyright 2003, Shiang-Ming Huang <smhuang@pcs.csie.nctu.edu.tw>
4
 * Copyright 2006, Marc Petit-Huguenin <marc@petit-huguenin.org>
5
 * Copyright 2007-2008, 8x8 Inc. <petithug@8x8.com>
6
 * Copyright 2008, Gael Breard <gael@breard.org>
7
 * Copyright 2013, Media5 Corporation, David Bergeron <dbergeron@media5corp.com>
8
 *
9
 * Wireshark - Network traffic analyzer
10
 * By Gerald Combs <gerald@wireshark.org>
11
 * Copyright 1998 Gerald Combs
12
 *
13
 * SPDX-License-Identifier: GPL-2.0-or-later
14
 *
15
 * Please refer to the following specs for protocol detail:
16
 * - RFC 3489 (Addition of deprecated attributes for diagnostics purpose)
17
 *             STUN - Simple Traversal of User Datagram Protocol (UDP)
18
 *             Through Network Address Translators (NATs) (superseded by RFC 5389)
19
 * - RFC 5389, formerly draft-ietf-behave-rfc3489bis-18
20
 *             Session Traversal Utilities for NAT (STUN) (superseded by RFC 8489)
21
 * - RFC 8489  Session Traversal Utilities for NAT (STUN)
22
 * - RFC 5780, formerly draft-ietf-behave-nat-behavior-discovery-08
23
 *             NAT Behavior Discovery Using Session Traversal Utilities for NAT (STUN)
24
 * - RFC 5766, formerly draft-ietf-behave-turn-16
25
 *             Traversal Using Relays around NAT (TURN) (superseded by RFC 8656)
26
 * - RFC 8656  Traversal Using Relays around NAT (TURN)
27
 * - RFC 6062  Traversal Using Relays around NAT (TURN) Extensions for TCP Allocations
28
 * - RFC 6156, formerly draft-ietf-behave-turn-ipv6-11
29
 *             Traversal Using Relays around NAT (TURN) Extension for IPv6
30
 * - RFC 5245, formerly draft-ietf-mmusic-ice-19
31
 *             Interactive Connectivity Establishment (ICE)
32
 * - RFC 6544  TCP Candidates with Interactive Connectivity Establishment (ICE)
33
 *
34
 * Iana registered values:
35
 * https://www.iana.org/assignments/stun-parameters/stun-parameters.xhtml
36
 *
37
 * From MS
38
 * MS-TURN: Traversal Using Relay NAT (TURN) Extensions https://docs.microsoft.com/en-us/openspecs/office_protocols/ms-turn
39
 * MS-TURNBWM:  Traversal using Relay NAT (TURN) Bandwidth Management Extensions https://docs.microsoft.com/en-us/openspecs/office_protocols/ms-turnbwm
40
 * MS-ICE: Interactive Connectivity Establishment (ICE) Extensions https://docs.microsoft.com/en-us/openspecs/office_protocols/ms-ice
41
 * MS-ICE2:  Interactive Connectivity Establishment ICE Extensions 2.0 https://docs.microsoft.com/en-us/openspecs/office_protocols/ms-ice2
42
 * MS-ICE2BWN: Interactive Connectivity Establishment (ICE) 2.0 Bandwidth Management Extensions https://docs.microsoft.com/en-us/openspecs/office_protocols/ms-ice2bwm
43
 */
44
45
/* TODO
46
 * Add information about different versions to table as we find it
47
 * Add/Implement missing attributes
48
 * Add/Implement missing message classes/methods
49
 * Add missing error codes
50
 */
51
52
#include "config.h"
53
54
#include <epan/packet.h>
55
#include <epan/expert.h>
56
#include <epan/to_str.h>
57
#include <epan/crc32-tvb.h>
58
#include <epan/tfs.h>
59
#include <wsutil/array.h>
60
#include <wsutil/ws_roundup.h>
61
#include "packet-tcp.h"
62
#include "packet-udp.h"
63
64
void proto_register_stun(void);
65
void proto_reg_handoff_stun(void);
66
67
/* Dissection relevant differences between STUN/TURN specification documents
68
 *
69
 *  Aspect   | MS-TURN 18.0       | RFC 3489           | RFC 5389           | RFC 8489 (*1)      |
70
 * ===============================================================================================
71
 *  Message  | 0b00+14-bit        | 16-bit             | 0b00+14-bit, type= |                    |
72
 *  Type     | No class or method | No class or method | class+method       |                    |
73
 *           | 0x0115: Data Ind   |                    | Method: 0x000-0xFFF| Method: 0x000-0x0FF|
74
 * -----------------------------------------------------------------------------------------------
75
 *  Transac- | 128 bits, seen     | 128 bits           | 32 bit Magic +     |                    |
76
 *  tion ID  | with MAGIC as well |                    | 96 bit Trans ID    |                    |
77
 * -----------------------------------------------------------------------------------------------
78
 *  Padding  | No Attribute Pad   | No Attribute Pad   | Pad to 32 bits     |                    |
79
 *           |                    |                    | Att. Len excl. Pad |                    |
80
 *           |                    |                    | Msg. Len incl. Pad |                    |
81
 *           |                    |                    |  -> MLen & 3 == 0  |                    |
82
 *           |                    |                    | Pad value: any     | Pad value: MBZ     |
83
 * -----------------------------------------------------------------------------------------------
84
 *  (XOR-)   | Write: Any value   | Write: Any value   | Write: MBZ         |                    |
85
 *  MAP-ADDR | Read : Ignored     | Read : Ignored     | Read : Ignored     |                    |
86
 *  1st byte |                    |                    |                    |                    |
87
 * -----------------------------------------------------------------------------------------------
88
 *  Username | Opaque             | Opaque             | UTF-8 String       |                    |
89
 * -----------------------------------------------------------------------------------------------
90
 *  Password | Opaque             | Deprecated         | Deprecated         |                    |
91
 * -----------------------------------------------------------------------------------------------
92
 *  NONCE &  | 0x0014             | 0x0015 (*2)        | 0x0015             |                    |
93
 *  REALM    | 0x0015             | 0x0014             | 0x0014             |                    |
94
 * -----------------------------------------------------------------------------------------------
95
 *  TURN     | RFC 5766/8656 or   | N/A                | RFC 5766:          | RFC 8656:          |
96
 *  Channels | Multiplexed TURN   |                    | 0x4000-0x7FFF used | 0x4000-0x4FFF used |
97
 *           | Channels (0xFF10)  |                    | 0x8000-0xFFFF res. | 0x5000-0xFFFF res. |
98
 *           |                    |                    | Reserved MUST NOT  | Reserved MUST be   |
99
 *           |                    |                    | be rejected        | dropped (collision)|
100
 * -----------------------------------------------------------------------------------------------
101
 * *1: Only where different from RFC 5389
102
 * *2: NONCE & REALM were first defined in Internet-Drafts after RFC 3489 was
103
 * published. Early drafts, up to draft-ietf-behave-rfc3489bis-02 and
104
 * draft-rosenberg-midcom-turn-08, used 0x0014 for NONCE and 0x0015 for REALM.
105
 * The attribute numbers were swapped in draft-ietf-behave-rfc3489bis-03 (when
106
 * moved from the TURN spec to the STUN spec), the same version that added the
107
 * fixed 32-bit magic. Since this dissector only handles packets with the magic
108
 * (others are rejected and processed by the classicstun dissector instead),
109
 * the swapped values are used for RFC 3489 mode here.
110
 */
111
112
enum {
113
        NET_VER_AUTO,
114
        NET_VER_MS_TURN,
115
        NET_VER_3489,
116
        NET_VER_5389
117
};
118
119
/* Auto-tuning. Default: NET_VER_5389; NET_VER_MS_TURN if MAGIC_COOKIE is found */
120
/* NET_VER_3489 is only useful for packets that conform specifically to
121
 * draft-ietf-behave-rfc3489bis-03; i.e. that have the 32 bit magic so that they
122
 * are not handled by classicstun instead, have the current (swapped) NONE and
123
 * REALM attribute numbers, but do not have the attribute padding that was
124
 * introduced in draft-ietf-behave-rfc3489bis-04.
125
 */
126
127
static int stun_network_version = NET_VER_5389;
128
129
static const enum_val_t stun_network_version_vals[] = {
130
        { "Auto", "Auto",     NET_VER_AUTO},
131
        { "MS-TURN",  "MS-TURN", NET_VER_MS_TURN },
132
        { "RFC3489", "RFC3489 and earlier",     NET_VER_3489},
133
        { "RFC5389",  "RFC5389 and later", NET_VER_5389 },
134
        { NULL, NULL, 0 }
135
};
136
137
static const value_string network_versions_vals[] = {
138
        {NET_VER_MS_TURN,  "MS-TURN"},
139
        {NET_VER_3489,     "RFC-3489 and earlier"},
140
        {NET_VER_5389,     "RFC-5389/8489"},
141
        {0,   NULL}
142
};
143
144
/* heuristic subdissectors */
145
static heur_dissector_list_t heur_subdissector_list;
146
147
/* stun dissector handles */
148
static dissector_handle_t data_handle;
149
static dissector_handle_t stun_tcp_handle;
150
static dissector_handle_t stun_udp_handle;
151
152
/* Initialize the protocol and registered fields */
153
static int proto_stun;
154
155
static int hf_stun_channel;
156
157
158
static int hf_stun_tcp_frame_length;
159
static int hf_stun_type;
160
static int hf_stun_type_class;
161
static int hf_stun_type_method;
162
static int hf_stun_type_method_assignment;
163
static int hf_stun_length;
164
static int hf_stun_cookie;
165
static int hf_stun_id;
166
static int hf_stun_attributes;
167
static int hf_stun_response_in;
168
static int hf_stun_response_to;
169
static int hf_stun_time;
170
static int hf_stun_duplicate;
171
static int hf_stun_attr;
172
173
static int hf_stun_att_type; /* STUN attribute fields */
174
static int hf_stun_att_length;
175
static int hf_stun_att_family;
176
static int hf_stun_att_type_comprehension;
177
static int hf_stun_att_type_assignment;
178
static int hf_stun_att_ipv4;
179
static int hf_stun_att_ipv6;
180
static int hf_stun_att_port;
181
static int hf_stun_att_username;
182
static int hf_stun_att_username_opaque;
183
static int hf_stun_att_password;
184
static int hf_stun_att_padding;
185
static int hf_stun_att_hmac;
186
static int hf_stun_att_crc32;
187
static int hf_stun_att_crc32_status;
188
static int hf_stun_att_error_class;
189
static int hf_stun_att_error_number;
190
static int hf_stun_att_error_reason;
191
static int hf_stun_att_realm;
192
static int hf_stun_att_nonce;
193
static int hf_stun_att_unknown;
194
static int hf_stun_att_xor_ipv4;
195
static int hf_stun_att_xor_ipv6;
196
static int hf_stun_att_xor_port;
197
static int hf_stun_att_icmp_type;
198
static int hf_stun_att_icmp_code;
199
static int hf_stun_att_ms_turn_unknown_8006;
200
static int hf_stun_att_software;
201
static int hf_stun_att_priority;
202
static int hf_stun_att_tie_breaker;
203
static int hf_stun_att_change_ip;
204
static int hf_stun_att_change_port;
205
static int hf_stun_att_cache_timeout;
206
static int hf_stun_att_token;
207
static int hf_stun_att_pw_alg;
208
static int hf_stun_att_pw_alg_param_len;
209
static int hf_stun_att_pw_alg_param_data;
210
static int hf_stun_att_reserve_next;
211
static int hf_stun_att_reserved;
212
static int hf_stun_att_value;
213
static int hf_stun_att_transp;
214
static int hf_stun_att_magic_cookie;
215
static int hf_stun_att_bandwidth;
216
static int hf_stun_att_lifetime;
217
static int hf_stun_att_channelnum;
218
static int hf_stun_att_ms_version;
219
static int hf_stun_att_ms_version_ice;
220
static int hf_stun_att_ms_connection_id;
221
static int hf_stun_att_ms_sequence_number;
222
static int hf_stun_att_ms_stream_type;
223
static int hf_stun_att_ms_service_quality;
224
static int hf_stun_att_ms_foundation;
225
static int hf_stun_att_ms_multiplexed_turn_session_id;
226
static int hf_stun_att_ms_turn_session_id;
227
static int hf_stun_att_bandwidth_acm_type;
228
static int hf_stun_att_bandwidth_rsv_id;
229
static int hf_stun_att_bandwidth_rsv_amount_misb;
230
static int hf_stun_att_bandwidth_rsv_amount_masb;
231
static int hf_stun_att_bandwidth_rsv_amount_mirb;
232
static int hf_stun_att_bandwidth_rsv_amount_marb;
233
static int hf_stun_att_address_rp_a;
234
static int hf_stun_att_address_rp_b;
235
static int hf_stun_att_address_rp_rsv1;
236
static int hf_stun_att_address_rp_rsv2;
237
static int hf_stun_att_address_rp_masb;
238
static int hf_stun_att_address_rp_marb;
239
static int hf_stun_att_sip_dialog_id;
240
static int hf_stun_att_sip_call_id;
241
static int hf_stun_att_lp_peer_location;
242
static int hf_stun_att_lp_self_location;
243
static int hf_stun_att_lp_federation;
244
static int hf_stun_att_google_network_id;
245
static int hf_stun_att_google_network_cost;
246
static int hf_stun_network_version;
247
248
/* Expert items */
249
static expert_field ei_stun_short_packet;
250
static expert_field ei_stun_wrong_msglen;
251
static expert_field ei_stun_long_attribute;
252
static expert_field ei_stun_unknown_attribute;
253
static expert_field ei_stun_fingerprint_bad;
254
255
/* Structure containing transaction specific information */
256
typedef struct _stun_transaction_t {
257
    uint32_t req_frame;
258
    uint32_t rep_frame;
259
    nstime_t req_time;
260
} stun_transaction_t;
261
262
/* Structure containing conversation specific information */
263
typedef struct _stun_conv_info_t {
264
    wmem_tree_t *transaction_pdus;
265
} stun_conv_info_t;
266
267
/* STUN versions RFC5389 and newer split off the leading 32 bits of the
268
 * transaction ID into a magic cookie (called message cookie in this
269
 * dissector to avoid confusion with the MAGIC_COOKIE attribute) and
270
 * shortens the real transaction ID to 96 bits.
271
 * This allows to differentiate between the legacy version of RFC3489
272
 * and all newer versions.
273
 */
274
4.84k
#define MESSAGE_COOKIE 0x2112A442
275
0
#define TURN_MAGIC_COOKIE 0x72C64BC6
276
277
/* Message classes (2 bit) */
278
164
#define REQUEST          0
279
0
#define INDICATION       1
280
124
#define SUCCESS_RESPONSE 2
281
0
#define ERROR_RESPONSE   3
282
283
284
/* Methods */
285
/* 0x000-0x07F IETF Review */
286
#define BINDING                 0x0001 /* RFC8489 */
287
#define SHARED_SECRET           0x0002 /* RFC3489 */
288
0
#define ALLOCATE                0x0003 /* RFC8489 */
289
0
#define REFRESH                 0x0004 /* RFC8489 */
290
/* 0x0005 is Unassigned.
291
 * 0x1115 was used for DATA_INDICATION in draft-rosenberg-midcom-turn-08,
292
 * but this did not fit the later class+indication scheme (it would
293
 * indicate an error response, which it is not) and was unassigned and
294
 * replaced with 0x0007 before RFC5389. The MS-TURN specification lists
295
 * it, however, and some MS-TURN captures use it.
296
 */
297
0
#define SEND                    0x0006 /* RFC8656 */
298
0
#define DATA_IND                0x0007 /* RFC8656 */
299
0
#define CREATE_PERMISSION       0x0008 /* RFC8656 */
300
0
#define CHANNELBIND             0x0009 /* RFC8656 */
301
/* TCP specific */
302
0
#define CONNECT                 0x000a /* RFC6062 */
303
0
#define CONNECTION_BIND         0x000b /* RFC6062 */
304
0
#define CONNECTION_ATTEMPT      0x000c /* RFC6062 */
305
#define GOOG_PING               0x0080 /* Google undocumented */
306
307
/* MS-TURN message types use raw 16-bit values, not the RFC 5389 class/method
308
 * bit layout used by the values above.
309
 */
310
0
#define MS_TURN_SEND    0x0004
311
0
#define MS_TURN_DATA_IND 0x0115
312
313
/* 0x080-0x0FF Expert Review */
314
/* 0x100-0xFFF Reserved (for DTLS-SRTP multiplexing collision avoidance,
315
 * see RFC7983.  Cannot be made available for assignment without IETF Review.)
316
 */
317
318
/* Attribute Types */
319
/* 0x0000-0x3FFF IETF Review comprehension-required range */
320
3
#define MAPPED_ADDRESS          0x0001 /* RFC8489, MS-TURN */
321
4
#define RESPONSE_ADDRESS        0x0002 /* Deprecated, RFC3489 */
322
5
#define CHANGE_REQUEST          0x0003 /* Deprecated, RFC3489 */
323
5
#define SOURCE_ADDRESS          0x0004 /* Deprecated, RFC3489 */
324
5
#define CHANGED_ADDRESS         0x0005 /* Deprecated, RFC3489 */
325
1
#define USERNAME                0x0006 /* RFC8489, MS-TURN */
326
1
#define PASSWORD                0x0007 /* Deprecated, RFC3489 */
327
3
#define MESSAGE_INTEGRITY       0x0008 /* RFC8489, MS-TURN */
328
0
#define ERROR_CODE              0x0009 /* RFC8489, MS-TURN */
329
3
#define UNKNOWN_ATTRIBUTES      0x000a /* RFC8489, MS-TURN */
330
5
#define REFLECTED_FROM          0x000b /* Deprecated, RFC3489 */
331
0
#define CHANNEL_NUMBER          0x000c /* RFC8656 */
332
0
#define LIFETIME                0x000d /* RFC8656, MS-TURN */
333
4
#define MS_ALTERNATE_SERVER     0x000e /* MS-TURN */
334
/* 0x000f reserved collision */
335
164
#define MAGIC_COOKIE            0x000f /* MS-TURN */
336
/* 0x0010 fix reference */
337
1
#define BANDWIDTH               0x0010 /* MS-TURN */
338
/* 0x0011 reserved collision */
339
5
#define DESTINATION_ADDRESS     0x0011 /* MS-TURN */
340
0
#define XOR_PEER_ADDRESS        0x0012 /* RFC8656, MS-TURN */
341
0
#define DATA                    0x0013 /* RFC8656, MS-TURN */
342
/* Note: REALM and NONCE have swapped attribute numbers in MS-TURN */
343
0
#define REALM                   0x0014 /* RFC8489, MS-TURN uses 0x0015 */
344
1
#define NONCE                   0x0015 /* RFC8489, MS-TURN uses 0x0014 */
345
0
#define XOR_RELAYED_ADDRESS     0x0016 /* RFC8656 */
346
0
#define REQUESTED_ADDRESS_FAMILY 0x0017 /* RFC8656, MS-TURN */
347
6
#define EVEN_PORT               0x0018 /* RFC8656 */
348
0
#define REQUESTED_TRANSPORT     0x0019 /* RFC8656 */
349
#define DONT_FRAGMENT           0x001a /* RFC8656 */
350
#define ACCESS_TOKEN            0x001b /* RFC7635 */
351
#define MESSAGE_INTEGRITY_SHA256 0x001c /* RFC8489 */
352
0
#define PASSWORD_ALGORITHM      0x001d /* RFC8489 */
353
#define USERHASH                0x001e /* RFC8489 */
354
/* 0x001f Reserved */
355
0
#define XOR_MAPPED_ADDRESS      0x0020 /* RFC8489 */
356
/* 0x0021 add deprecated TIMER-VAL */
357
0
#define RESERVATION_TOKEN       0x0022 /* RFC8656 */
358
/* 0x0023 Reserved */
359
0
#define PRIORITY                0x0024 /* RFC8445 */
360
#define USE_CANDIDATE           0x0025 /* RFC8445 */
361
0
#define PADDING                 0x0026 /* RFC5780 */
362
/* 0x0027 collision RESPONSE-PORT RFC5780 */
363
1
#define XOR_RESPONSE_TARGET     0x0027 /* draft-ietf-behave-nat-behavior-discovery-03 */
364
/* 0x0028 Reserved collision */
365
2
#define XOR_REFLECTED_FROM      0x0028 /* draft-ietf-behave-nat-behavior-discovery-03 */
366
/* 0x0029 Reserved */
367
#define CONNECTION_ID           0x002a /* rfc6062 */
368
/* 0x002b-0x002f unassigned */
369
/* 0x0030 collision reserved */
370
1
#define LEGACY_ICMP             0x0030 /* Moved from TURN to 0x8004 */
371
/* 0x0031-0x3fff Unassigned */
372
373
/* 0x4000-0x7FFF Expert Review comprehension-required range */
374
/* 0x4000-0x7fff Unassigned */
375
/* WhatsApp is known to use 0x4000, 0x4002, and 0x4024 */
376
377
/* 0x8000-0xBFFF IETF Review comprehension-optional range */
378
#define ADDITIONAL_ADDRESS_FAMILY 0x8000 /* RFC8656 */
379
#define ADDRESS_ERROR_CODE      0x8001 /* RFC8656 */
380
0
#define PASSWORD_ALGORITHMS     0x8002 /* RFC8489 */
381
#define ALTERNATE_DOMAIN        0x8003 /* RFC8489 */
382
1
#define ICMP                    0x8004 /* RFC8656 */
383
/* Unknown attribute in MS-TURN packets */
384
0
#define MS_TURN_UNKNOWN_8006  0x8006
385
/* 0x8005-0x8021 Unassigned collision */
386
0
#define MS_VERSION              0x8008 /* MS-TURN */
387
/* collision */
388
2
#define MS_XOR_MAPPED_ADDRESS   0x8020 /* MS-TURN */
389
0
#define SOFTWARE                0x8022 /* RFC8489 */
390
3
#define ALTERNATE_SERVER        0x8023 /* RFC8489 */
391
/* 0x8024 Reserved */
392
#define TRANSACTION_TRANSMIT_COUNTER 0x8025 /* RFC7982 */
393
/* 0x8026 Reserved */
394
0
#define CACHE_TIMEOUT           0x8027 /* RFC5780 */
395
0
#define FINGERPRINT             0x8028 /* RFC8489 */
396
0
#define ICE_CONTROLLED          0x8029 /* RFC8445 */
397
0
#define ICE_CONTROLLING         0x802a /* RFC8445 */
398
3
#define RESPONSE_ORIGIN         0x802b /* RFC5780 */
399
3
#define OTHER_ADDRESS           0x802c /* RFC5780 */
400
#define ECN_CHECK_STUN          0x802d /* RFC6679 */
401
#define THIRD_PARTY_AUTHORIZATION 0x802e /* RFC7635 */
402
/* 0x802f Unassigned */
403
#define MOBILITY_TICKET         0x8030 /* RFC8016 */
404
/* 0x8031-0xBFFF Unassigned collision */
405
#define MS_ALTERNATE_HOST_NAME  0x8032 /* MS-TURN */
406
#define MS_APP_ID               0x8037 /* MS-TURN */
407
#define MS_SECURE_TAG           0x8039 /* MS-TURN */
408
0
#define MS_SEQUENCE_NUMBER      0x8050 /* MS-TURN */
409
0
#define MS_CANDIDATE_IDENTIFIER 0x8054 /* MS-ICE2 */
410
0
#define MS_SERVICE_QUALITY      0x8055 /* MS-TURN */
411
0
#define BANDWIDTH_ACM           0x8056 /* MS-TURNBWM */
412
0
#define BANDWIDTH_RSV_ID        0x8057 /* MS-TURNBWM */
413
0
#define BANDWIDTH_RSV_AMOUNT    0x8058 /* MS-TURNBWM */
414
2
#define REMOTE_SITE_ADDR        0x8059 /* MS-TURNBWM */
415
2
#define REMOTE_RELAY_SITE       0x805A /* MS-TURNBWM */
416
2
#define LOCAL_SITE_ADDR         0x805B /* MS-TURNBWM */
417
2
#define LOCAL_RELAY_SITE        0x805C /* MS-TURNBWM */
418
0
#define REMOTE_SITE_ADDR_RP     0x805D /* MS-TURNBWM */
419
0
#define REMOTE_RELAY_SITE_RP    0x805E /* MS-TURNBWM */
420
0
#define LOCAL_SITE_ADDR_RP      0x805F /* MS-TURNBWM */
421
0
#define LOCAL_RELAY_SITE_RP     0x8060 /* MS-TURNBWM */
422
0
#define SIP_DIALOG_ID           0x8061 /* MS-TURNBWM */
423
0
#define SIP_CALL_ID             0x8062 /* MS-TURNBWM */
424
0
#define LOCATION_PROFILE        0x8068 /* MS-TURNBWM */
425
0
#define MS_IMPLEMENTATION_VER   0x8070 /* MS-ICE2 */
426
3
#define MS_ALT_MAPPED_ADDRESS   0x8090 /* MS-TURN */
427
0
#define MS_MULTIPLEXED_TURN_SESSION_ID 0x8095 /* MS_TURN */
428
429
/* 0xC000-0xFFFF Expert Review comprehension-optional range */
430
#define CISCO_STUN_FLOWDATA     0xc000 /* Cisco undocumented */
431
#define ENF_FLOW_DESCRIPTION    0xc001 /* Cisco undocumented */
432
#define ENF_NETWORK_STATUS      0xc002 /* Cisco undocumented */
433
/* 0xc003-0xc056 Unassigned */
434
/* https://webrtc.googlesource.com/src/+/refs/heads/master/api/transport/stun.h */
435
0
#define GOOG_NETWORK_INFO       0xc057
436
#define GOOG_LAST_ICE_CHECK_RECEIVED 0xc058
437
#define GOOG_MISC_INFO          0xc059
438
/* Various IANA-registered but undocumented Google attributes follow */
439
#define GOOG_OBSOLETE_1         0xc05a
440
#define GOOG_CONNECTION_ID      0xc05b
441
#define GOOG_DELTA              0xc05c
442
#define GOOG_DELTA_ACK          0xc05d
443
/* 0xc05e-0xc05f Unassigned */
444
#define GOOG_MESSAGE_INTEGRITY_32 0xc060
445
/* 0xc061-0xff03 Unassigned */
446
/* https://webrtc.googlesource.com/src/+/refs/heads/master/p2p/base/turn_port.cc */
447
#define GOOG_MULTI_MAPPING      0xff04
448
#define GOOG_LOGGING_ID         0xff05
449
/* 0xff06-0xffff Unassigned */
450
451
193
#define MS_MULTIPLEX_TURN 0xFF10
452
453
/* Initialize the subtree pointers */
454
static int ett_stun;
455
static int ett_stun_type;
456
static int ett_stun_att_all;
457
static int ett_stun_att;
458
static int ett_stun_att_type;
459
460
16
#define UDP_PORT_STUN   3478
461
16
#define TCP_PORT_STUN   3478
462
463
2.88k
#define STUN_HDR_LEN                   20 /* STUN message header length */
464
210
#define ATTR_HDR_LEN                    4 /* STUN attribute header length */
465
201
#define CHANNEL_DATA_HDR_LEN            4 /* TURN CHANNEL-DATA Message hdr length */
466
8.61k
#define MIN_HDR_LEN                     4
467
3.34k
#define TCP_FRAME_COOKIE_LEN           10 /* min length for cookie with TCP framing */
468
469
static const value_string transportnames[] = {
470
    {  6, "TCP" },
471
    { 17, "UDP" },
472
    {  0, NULL }
473
};
474
475
static const value_string classes[] = {
476
    {REQUEST         , "Request"},
477
    {INDICATION      , "Indication"},
478
    {SUCCESS_RESPONSE, "Success Response"},
479
    {ERROR_RESPONSE  , "Error Response"},
480
    {0x00            , NULL}
481
};
482
483
static const value_string methods[] = {
484
    {BINDING           , "Binding"},
485
    {SHARED_SECRET     , "SharedSecret"},
486
    {ALLOCATE          , "Allocate"},
487
    {REFRESH           , "Refresh"},
488
    {SEND              , "Send"},
489
    {DATA_IND          , "Data"},
490
    {CREATE_PERMISSION , "CreatePermission"},
491
    {CHANNELBIND       , "Channel-Bind"},
492
    {CONNECT           , "Connect"},
493
    {CONNECTION_BIND   , "ConnectionBind"},
494
    {CONNECTION_ATTEMPT, "ConnectionAttempt"},
495
    {GOOG_PING         , "GooglePing"},
496
    {0x00              , NULL}
497
};
498
499
500
static const value_string attributes[] = {
501
  /* 0x0000-0x3FFF IETF Review comprehension-required range */
502
    {MAPPED_ADDRESS        , "MAPPED-ADDRESS"},
503
    {RESPONSE_ADDRESS      , "RESPONSE_ADDRESS"},
504
    {CHANGE_REQUEST        , "CHANGE_REQUEST"},
505
    {SOURCE_ADDRESS        , "SOURCE_ADDRESS"},
506
    {CHANGED_ADDRESS       , "CHANGED_ADDRESS"},
507
    {USERNAME              , "USERNAME"},
508
    {PASSWORD              , "PASSWORD"},
509
    {MESSAGE_INTEGRITY     , "MESSAGE-INTEGRITY"},
510
    {ERROR_CODE            , "ERROR-CODE"},
511
    {UNKNOWN_ATTRIBUTES    , "UNKNOWN-ATTRIBUTES"},
512
    {REFLECTED_FROM        , "REFLECTED-FROM"},
513
    {CHANNEL_NUMBER        , "CHANNEL-NUMBER"},
514
    {LIFETIME              , "LIFETIME"},
515
    {MS_ALTERNATE_SERVER   , "MS-ALTERNATE-SERVER"},
516
    {MAGIC_COOKIE          , "MAGIC-COOKIE"},
517
    {BANDWIDTH             , "BANDWIDTH"},
518
    {DESTINATION_ADDRESS   , "DESTINATION-ADDRESS"},
519
    {XOR_PEER_ADDRESS      , "XOR-PEER-ADDRESS"},
520
    {DATA                  , "DATA"},
521
    {REALM                 , "REALM"},
522
    {NONCE                 , "NONCE"},
523
    {XOR_RELAYED_ADDRESS   , "XOR-RELAYED-ADDRESS"},
524
    {REQUESTED_ADDRESS_FAMILY, "REQUESTED-ADDRESS-FAMILY"},
525
    {EVEN_PORT             , "EVEN-PORT"},
526
    {REQUESTED_TRANSPORT   , "REQUESTED-TRANSPORT"},
527
    {DONT_FRAGMENT         , "DONT-FRAGMENT"},
528
    {ACCESS_TOKEN          , "ACCESS-TOKEN"},
529
    {MESSAGE_INTEGRITY_SHA256, "MESSAGE-INTEGRITY-SHA256"},
530
    {PASSWORD_ALGORITHM    , "PASSWORD-ALGORITHM"},
531
    {USERHASH              , "USERHASH"},
532
    {XOR_MAPPED_ADDRESS    , "XOR-MAPPED-ADDRESS"},
533
    {RESERVATION_TOKEN     , "RESERVATION-TOKEN"},
534
    {PRIORITY              , "PRIORITY"},
535
    {USE_CANDIDATE         , "USE-CANDIDATE"},
536
    {PADDING               , "PADDING"},
537
    {XOR_RESPONSE_TARGET   , "XOR-RESPONSE-TARGET"},
538
    {XOR_REFLECTED_FROM    , "XOR-REFELECTED-FROM"},
539
    {CONNECTION_ID         , "CONNECTION-ID"},
540
    {LEGACY_ICMP           , "LEGACY-ICMP"},
541
542
  /* 0x4000-0x7FFF Expert Review comprehension-required range */
543
544
  /* 0x8000-0xBFFF IETF Review comprehension-optional range */
545
    {ADDITIONAL_ADDRESS_FAMILY, "ADDITIONAL-ADDRESS-FAMILY"},
546
    {ADDRESS_ERROR_CODE    , "ADDRESS-ERROR-CODE"},
547
    {PASSWORD_ALGORITHMS   , "PASSWORD-ALGORITHMS"},
548
    {ALTERNATE_DOMAIN      , "ALTERNATE-DOMAIN"},
549
    {ICMP                  , "ICMP"},
550
    {MS_TURN_UNKNOWN_8006  , "MS-TURN UNKNOWN 8006"},
551
    {MS_VERSION            , "MS-VERSION"},
552
    {MS_XOR_MAPPED_ADDRESS , "MS-XOR-MAPPED-ADDRESS"},
553
    {SOFTWARE              , "SOFTWARE"},
554
    {ALTERNATE_SERVER      , "ALTERNATE-SERVER"},
555
    {TRANSACTION_TRANSMIT_COUNTER, "TRANSACTION-TRANSMIT-COUNTER"},
556
    {CACHE_TIMEOUT         , "CACHE-TIMEOUT"},
557
    {FINGERPRINT           , "FINGERPRINT"},
558
    {ICE_CONTROLLED        , "ICE-CONTROLLED"},
559
    {ICE_CONTROLLING       , "ICE-CONTROLLING"},
560
    {RESPONSE_ORIGIN       , "RESPONSE-ORIGIN"},
561
    {OTHER_ADDRESS         , "OTHER-ADDRESS"},
562
    {ECN_CHECK_STUN        , "ECN-CHECK-STUN"},
563
    {THIRD_PARTY_AUTHORIZATION, "THIRD-PARTY-AUTHORIZATION"},
564
    {MOBILITY_TICKET       , "MOBILITY-TICKET"},
565
    {MS_ALTERNATE_HOST_NAME, "MS-ALTERNATE-HOST-NAME"},
566
    {MS_APP_ID             , "MS-APP-ID"},
567
    {MS_SECURE_TAG         , "MS-SECURE-TAG"},
568
    {MS_SEQUENCE_NUMBER    , "MS-SEQUENCE-NUMBER"},
569
    {MS_CANDIDATE_IDENTIFIER, "MS-CANDIDATE-IDENTIFIER"},
570
    {MS_SERVICE_QUALITY    , "MS-SERVICE-QUALITY"},
571
    {BANDWIDTH_ACM         , "Bandwidth Admission Control Message"},
572
    {BANDWIDTH_RSV_ID      , "Bandwidth Reservation Identifier"},
573
    {BANDWIDTH_RSV_AMOUNT  , "Bandwidth Reservation Amount"},
574
    {REMOTE_SITE_ADDR      , "Remote Site Address"},
575
    {REMOTE_RELAY_SITE     , "Remote Relay Site Address"},
576
    {LOCAL_SITE_ADDR       , "Local Site Address"},
577
    {LOCAL_RELAY_SITE      , "Local Relay Site Address"},
578
    {REMOTE_SITE_ADDR_RP   , "Remote Site Address Response"},
579
    {REMOTE_RELAY_SITE_RP  , "Remote Relay Site Address Response"},
580
    {LOCAL_SITE_ADDR_RP    , "Local Site Address Response"},
581
    {LOCAL_RELAY_SITE_RP   , "Local Relay Site Address Response"},
582
    {SIP_DIALOG_ID         , "SIP Dialog Identifier"},
583
    {SIP_CALL_ID           , "SIP Call Identifier"},
584
    {LOCATION_PROFILE      , "Location Profile"},
585
    {MS_IMPLEMENTATION_VER , "MS-IMPLEMENTATION-VERSION"},
586
    {MS_ALT_MAPPED_ADDRESS , "MS-ALT-MAPPED-ADDRESS"},
587
    {MS_MULTIPLEXED_TURN_SESSION_ID, "MS-MULTIPLEXED-TURN-SESSION-ID"},
588
589
  /* 0xC000-0xFFFF Expert Review comprehension-optional range */
590
    {CISCO_STUN_FLOWDATA   , "CISCO-STUN-FLOWDATA"},
591
    {ENF_FLOW_DESCRIPTION   , "ENF-FLOW-DESCRIPTION"},
592
    {ENF_NETWORK_STATUS    , "ENF-NETWORK-STATUS"},
593
    {GOOG_NETWORK_INFO     , "GOOG-NETWORK-INFO"},
594
    {GOOG_LAST_ICE_CHECK_RECEIVED, "GOOG-LAST-ICE-CHECK-RECEIVED"},
595
    {GOOG_MISC_INFO        , "GOOG-MISC-INFO"},
596
    {GOOG_OBSOLETE_1       , "GOOG-OBSOLETE-1"},
597
    {GOOG_CONNECTION_ID    , "GOOG-CONNECTION-ID"},
598
    {GOOG_DELTA            , "GOOG-DELTA"},
599
    {GOOG_DELTA_ACK        , "GOOG-DELTA-ACK"},
600
    {GOOG_MESSAGE_INTEGRITY_32, "GOOG-MESSAGE_INTEGRITY-32"},
601
    {GOOG_MULTI_MAPPING    , "GOOG-MULTI-MAPPING"},
602
    {GOOG_LOGGING_ID       , "GOOG-LOGGING-ID"},
603
604
    {0x00                  , NULL}
605
};
606
static value_string_ext attributes_ext = VALUE_STRING_EXT_INIT(attributes);
607
608
static const value_string assignments[] = {
609
    {0x0000, "IETF Review"},
610
    {0x0001, "Designated Expert"},
611
    {0x00, NULL}
612
};
613
614
static const value_string comprehensions[] = {
615
    {0x0000, "Required"},
616
    {0x0001, "Optional"},
617
    {0x00  , NULL}
618
};
619
620
static const value_string attributes_reserve_next[] = {
621
    {0, "No reservation"},
622
    {1, "Reserve next port number"},
623
    {0x00, NULL}
624
};
625
626
static const value_string attributes_family[] = {
627
    {0x0001, "IPv4"},
628
    {0x0002, "IPv6"},
629
    {0x00, NULL}
630
};
631
/* https://www.iana.org/assignments/stun-parameters/stun-parameters.xhtml#stun-parameters-6 (2020-08-05)*/
632
633
static const value_string error_code[] = {
634
    {274, "Disable Candidate"},               /* MS-ICE2BWN */
635
    {275, "Disable Candidate Pair"},          /* MS-ICE2BWN */
636
    {300, "Try Alternate"},                   /* RFC8489 */
637
    {400, "Bad Request"},                     /* RFC8489 */
638
    {401, "Unauthenticated"},                 /* RFC8489, RFC3489+MS-TURN: Unauthorized */
639
    {403, "Forbidden"},                       /* RFC8656 */
640
    {405, "Mobility Forbidden"},              /* RFC8016 */
641
    {420, "Unknown Attribute"},               /* RFC8489 */
642
    {430, "Stale Credentials (legacy)"},      /* RFC3489 */
643
    {431, "Integrity Check Failure (legacy)"}, /* RFC3489 */
644
    {432, "Missing Username (legacy)"},       /* RFC3489 */
645
    {433, "Use TLS (legacy)"},                /* RFC3489 */
646
    {434, "Missing Realm (legacy)"},          /* MS-TURN */
647
    {435, "Missing Nonce (legacy)"},          /* MS-TURN */
648
    {436, "Unknown User (legacy)"},           /* MS-TURN */
649
    {437, "Allocation Mismatch"},             /* RFC8656 */
650
    {438, "Stale Nonce"},                     /* RFC8489 */
651
    {439, "Wrong Credentials (legacy)"},      /* turn-07 */
652
    {440, "Address Family not Supported"},    /* RFC8656 */
653
    {441, "Wrong Credentials"},               /* RFC8656 */
654
    {442, "Unsupported Transport Protocol"},  /* RFC8656 */
655
    {443, "Peer Address Family Mismatch"},    /* RFC8656 */
656
    {446, "Connection Already Exists"},       /* RFC6062 */
657
    {447, "Connection Timeout or Failure"},   /* RFC6062 */
658
    {481, "Connection does not exist (legacy)"}, /* nat-behavior-discovery-03 */
659
    {486, "Allocation Quota Reached"},        /* RFC8656 */
660
    {487, "Role Conflict"},                   /* RFC8445 */
661
    {500, "Server Error"},                    /* RFC8489 */
662
    {503, "Service Unavailable (legacy)"},    /* nat-behavior-discovery-03 */
663
    {507, "Insufficient Bandwidth Capacity (legacy)"}, /* turn-07 */
664
    {508, "Insufficient Port Capacity"},      /* RFC8656 */
665
    {600, "Global Failure"},                  /* RFC8656 */
666
    {0x00, NULL}
667
};
668
static value_string_ext error_code_ext = VALUE_STRING_EXT_INIT(error_code);
669
670
static const value_string ms_version_vals[] = {
671
    {0x00000001, "ICE"},
672
    {0x00000002, "MS-ICE2"},
673
    {0x00000003, "MS-ICE2 with SHA256"},
674
    {0x00000004, "MS-ICE2 with SHA256 and IPv6"},
675
    {0x00000005, "MULTIPLEXED TURN over UDP only"},
676
    {0x00000006, "MULTIPLEXED TURN over UDP and TCP"},
677
    {0x00, NULL}
678
};
679
680
static const range_string ms_version_ice_rvals[] = {
681
    {0x00000000, 0x00000002, "Supports only RFC3489bis-02 message formats"},
682
    {0x00000003, 0xFFFFFFFF, "Supports RFC5389 message formats"},
683
    {0x00, 0x00, NULL}
684
};
685
686
static const value_string ms_stream_type_vals[] = {
687
    {0x0001, "Audio"},
688
    {0x0002, "Video"},
689
    {0x0003, "Supplemental Video"},
690
    {0x0004, "Data"},
691
    {0x00, NULL}
692
};
693
694
static const value_string ms_service_quality_vals[] = {
695
    {0x0000, "Best effort delivery"},
696
    {0x0001, "Reliable delivery"},
697
    {0x00, NULL}
698
};
699
700
static const value_string bandwidth_acm_type_vals[] = {
701
    {0x0000, "Reservation Check"},
702
    {0x0001, "Reservation Commit"},
703
    {0x0002, "Reservation Update"},
704
    {0x00, NULL}
705
};
706
707
static const value_string location_vals[] = {
708
    {0x00, "Unknown"},
709
    {0x01, "Internet"},
710
    {0x02, "Intranet"},
711
    {0x00, NULL}
712
};
713
714
static const value_string federation_vals[] = {
715
    {0x00, "No Federation"},
716
    {0x01, "Enterprise Federation"},
717
    {0x02, "Public Cloud Federation"},
718
    {0x00, NULL}
719
};
720
721
static const value_string password_algorithm_vals[] = {
722
    {0x0000, "Reserved"},
723
    {0x0001, "MD5"},
724
    {0x0002, "SHA-256"},
725
    {0x0000, NULL}
726
};
727
728
/* https://webrtc.googlesource.com/src/+/refs/heads/master/rtc_base/network_constants.h */
729
static const value_string google_network_cost_vals[] = {
730
    {0,   "Min"},
731
    {10,  "Low"},
732
    {50,  "Unknown"},
733
    {250, "Cellular5G"},
734
    {500, "Cellular4G"},
735
    {900, "Cellular"},
736
    {910, "Cellular3G"},
737
    {980, "Cellular2G"},
738
    {999, "Max"},
739
    {0,   NULL}
740
};
741
742
/* Test for STUN starting at offset - note that for STUN over TCP with
743
 * RFC 4571/6544 framing, offset should be adjusted before passing in
744
 * here.
745
 */
746
static bool
747
test_stun(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, bool heur_check, bool is_udp)
748
4.07k
{
749
4.07k
    unsigned    captured_length;
750
4.07k
    unsigned    reported_length;
751
4.07k
    uint16_t    msg_type;
752
4.07k
    unsigned    msg_length;
753
    /*
754
     * Check if the frame is really meant for us.
755
     */
756
757
    /* First, make sure we have enough data to do the check. */
758
4.07k
    captured_length = tvb_captured_length_remaining(tvb, offset);
759
4.07k
    if (captured_length < MIN_HDR_LEN)
760
151
        return false;
761
3.91k
    reported_length = tvb_captured_length_remaining(tvb, offset);
762
763
3.91k
    msg_type     = tvb_get_ntohs(tvb, offset);
764
3.91k
    msg_length   = tvb_get_ntohs(tvb, offset + 2);
765
766
    /* TURN ChannelData message ? */
767
3.91k
    if (msg_type & 0xC000) {
768
        /* two first bits not NULL => should be a channel-data message */
769
770
        /*
771
         * If the packet is being dissected through heuristics, we never match
772
         * TURN ChannelData because the heuristics are otherwise rather weak.
773
         * Instead we have to have seen another STUN message type on the same
774
         * 5-tuple, and then set that conversation for non-heuristic STUN
775
         * dissection.
776
         */
777
1.88k
        if (heur_check)
778
1.88k
            return false;
779
780
        /* RFC 5764 defined a demultiplexing scheme to allow STUN to co-exist
781
         * on the same 5-tuple as DTLS-SRTP (and ZRTP) by rejecting previously
782
         * reserved channel numbers and method types, implicitly restricting
783
         * channel numbers to 0x4000-0x7FFF.  RFC 5766 did not incorporate this
784
         * restriction, instead indicating that reserved numbers MUST NOT be
785
         * dropped.
786
         * RFCs 7983, 8489, and 8656 reconciled this and formally indicated
787
         * that channel numbers in the reserved range MUST be dropped, while
788
         * further restricting the channel numbers to 0x4000-0x4FFF.
789
         * Reject the range 0x8000-0xFFFF, except for the special
790
         * MS-TURN multiplex channel number, since no implementation has
791
         * used any other value in that range (that we know of).
792
         */
793
2
        if (msg_type & 0x8000 && msg_type != MS_MULTIPLEX_TURN) {
794
1
            return false;
795
1
        }
796
797
        /* "Over TCP and TLS-over-TCP, the ChannelData message MUST be padded to
798
         * a multiple of 4 bytes (not reflected in the length field)... Over UDP,
799
         * the padding is optional but MAY be included." - RFC 8656, 12.5
800
         */
801
1
        if (is_udp) {
802
1
            if (reported_length != msg_length + CHANNEL_DATA_HDR_LEN &&
803
1
                reported_length != ((msg_length + CHANNEL_DATA_HDR_LEN + 3) & ~0x3))
804
1
                return false;
805
1
        } else { /* TCP or TLS-over-TCP */
806
0
            if (reported_length != ((msg_length + CHANNEL_DATA_HDR_LEN + 3) & ~0x3))
807
0
                return false;
808
0
        }
809
810
0
        return true;
811
1
    }
812
813
    /* Normal STUN message */
814
2.03k
    if (captured_length < STUN_HDR_LEN)
815
541
        return false;
816
817
1.49k
    uint16_t msg_type_method = (msg_type & 0x000F) | ((msg_type & 0x00E0) >> 1) | ((msg_type & 0x3E00) >> 2);
818
819
1.49k
    if (msg_type_method > 0x3FF) {
820
        /* All values > 0xFF are "Reserved for DTLS-SRTP multiplexing collision
821
         * avoidance, see RFC 7983. Cannot be made available for assignment
822
         * without IETF Review."
823
         *
824
         * However, values of the first byte between 4 and 15 (corresponding with
825
         * methods from 0x100 to 0x3FF) are not included in the multiplexing
826
         * scheme and explicitly dropped in RFC 9443. Some of the higher values
827
         * (notably 0x201, 0x202) are used by WhatsApp's implementation of STUN.
828
         * (#20560). Since RFC 9443 recommends dropping the packet, and no
829
         * other protocol as of yet has these values, if the 4-byte cookie is
830
         * present that should be sufficient to call it STUN.
831
         *
832
         * If that is too generous, we could allow only the methods known to
833
         * be used by WhatsApp.
834
         */
835
476
    }
836
837
    /* Check if it is really a STUN message - reject messages without the
838
     * RFC 5389 Magic and let the classicstun dissector handle those.
839
     */
840
1.49k
    if ( tvb_get_ntohl(tvb, offset + 4) != MESSAGE_COOKIE)
841
1.47k
        return false;
842
843
    /* check if payload enough */
844
22
    if (reported_length < (msg_length + STUN_HDR_LEN + offset))
845
1
        return false;
846
847
    /* The message seems to be a valid STUN message! */
848
21
    return true;
849
22
}
850
851
static bool
852
test_stun_udp_heur(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
853
1.27k
{
854
1.27k
    return test_stun(pinfo, tvb, offset, true, true);
855
1.27k
}
856
857
static bool
858
test_stun_udp(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
859
34
{
860
34
    return test_stun(pinfo, tvb, offset, false, true);
861
34
}
862
863
static unsigned
864
get_stun_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
865
                     int offset, void *data _U_)
866
292
{
867
292
    uint16_t type;
868
292
    unsigned   length;
869
292
    unsigned   captured_length = tvb_captured_length(tvb);
870
871
292
    if ((captured_length >= TCP_FRAME_COOKIE_LEN) &&
872
291
        (tvb_get_ntohl(tvb, 6) == MESSAGE_COOKIE)) {
873
        /*
874
         * The magic cookie is off by two, so this appears to be
875
         * RFC 4571 framing, as per RFC 6544; use the length
876
         * field from that framing, rather than the STUN/TURN
877
         * ChannelData length field.
878
         */
879
7
        return (tvb_get_ntohs(tvb, offset) + 2);
880
7
    }
881
882
285
    type   = tvb_get_ntohs(tvb, offset);
883
285
    length = tvb_get_ntohs(tvb, offset+2);
884
885
285
    if (type & 0xC000)
886
64
    {
887
        /* two first bits not NULL => should be a channel-data message */
888
        /* Note: For TCP the message is padded to a 4 byte boundary    */
889
64
        return (length + CHANNEL_DATA_HDR_LEN +3) & ~0x3;
890
64
    }
891
221
    else
892
221
    {
893
        /* Normal STUN message */
894
221
        return length + STUN_HDR_LEN;
895
221
    }
896
285
}
897
898
/*
899
 * XXX: why is this done in this file by the STUN dissector? Why don't we
900
 * re-use the packet-turnchannel.c's dissect_turnchannel_message() function?
901
 */
902
static int
903
dissect_stun_message_channel_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint16_t msg_type, unsigned msg_length)
904
44
{
905
44
    tvbuff_t *next_tvb;
906
44
    heur_dtbl_entry_t *hdtbl_entry;
907
44
    int offset = CHANNEL_DATA_HDR_LEN;
908
909
    /* XXX: a TURN ChannelData message is not actually a STUN message. */
910
44
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "STUN");
911
44
    col_set_str(pinfo->cinfo, COL_INFO, "ChannelData TURN Message");
912
913
44
    if (tree) {
914
44
        proto_item *ti;
915
44
        proto_tree *stun_tree;
916
44
        ti = proto_tree_add_item(
917
44
            tree, proto_stun, tvb, 0,
918
44
            CHANNEL_DATA_HDR_LEN,
919
44
            ENC_NA);
920
44
        proto_item_append_text(ti, ", TURN ChannelData Message");
921
44
        stun_tree = proto_item_add_subtree(ti, ett_stun);
922
44
        proto_tree_add_item(stun_tree, hf_stun_channel, tvb, 0, 2, ENC_BIG_ENDIAN);
923
44
        proto_tree_add_item(stun_tree, hf_stun_length,  tvb, 2, 2, ENC_BIG_ENDIAN);
924
        /* MS-TURN Multiplexed TURN Channel */
925
44
        if (msg_type == MS_MULTIPLEX_TURN && msg_length >= 8) {
926
0
            proto_tree_add_item(stun_tree, hf_stun_att_ms_turn_session_id, tvb, 4, 8, ENC_BIG_ENDIAN);
927
0
        }
928
44
    }
929
44
    if (msg_type == MS_MULTIPLEX_TURN && msg_length >= 8) {
930
0
        msg_length -= 8;
931
0
        offset += 8;
932
0
    }
933
934
44
    next_tvb = tvb_new_subset_length(tvb, offset, msg_length);
935
936
44
    if (!dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
937
36
        call_dissector_only(data_handle, next_tvb, pinfo, tree, NULL);
938
36
    }
939
940
44
    return tvb_reported_length(tvb);
941
44
}
942
943
944
static int
945
dissect_stun_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, bool is_udp)
946
291
{
947
291
    unsigned    captured_length;
948
291
    uint16_t    msg_type;
949
291
    unsigned    msg_length;
950
291
    proto_item *ti, *ti_length;
951
291
    proto_tree *stun_tree;
952
291
    proto_tree *stun_type_tree;
953
291
    proto_tree *att_all_tree;
954
291
    proto_tree *att_type_tree;
955
291
    proto_tree *att_tree = NULL;
956
291
    uint16_t    msg_type_method;
957
291
    uint16_t    msg_type_class;
958
291
    const char *msg_class_str;
959
291
    const char *msg_method_str;
960
291
    uint16_t    att_type, att_type_display;
961
291
    uint16_t    att_length, att_length_pad, clear_port;
962
291
    uint32_t    clear_ip[4];
963
291
    address     addr;
964
291
    unsigned    i;
965
291
    unsigned    offset;
966
291
    unsigned    magic_cookie_first_word;
967
291
    unsigned    tcp_framing_offset;
968
291
    conversation_t     *conversation=NULL;
969
291
    stun_conv_info_t   *stun_info;
970
291
    stun_transaction_t *stun_trans;
971
291
    wmem_tree_key_t     transaction_id_key[2];
972
291
    uint32_t            transaction_id[3];
973
291
    heur_dtbl_entry_t  *hdtbl_entry;
974
291
    unsigned            reported_length;
975
291
    bool                is_turn = false;
976
291
    bool                found_turn_attributes = false;
977
291
    int                 network_version; /* STUN flavour of the current message */
978
979
    /*
980
     * Check if the frame is really meant for us.
981
     */
982
983
    /* First, make sure we have enough data to do the check. */
984
291
    captured_length = tvb_captured_length(tvb);
985
291
    if (captured_length < MIN_HDR_LEN)
986
0
        return 0;
987
291
    reported_length = tvb_reported_length(tvb);
988
989
291
    tcp_framing_offset = 0;
990
291
    if ((!is_udp) && (captured_length >= TCP_FRAME_COOKIE_LEN) &&
991
273
       (tvb_get_ntohl(tvb, 6) == MESSAGE_COOKIE)) {
992
        /*
993
         * The magic cookie is off by two, so this appears to be
994
         * RFC 4571 framing, as per RFC 6544; the STUN/TURN
995
         * ChannelData header begins after the 2-octet
996
         * RFC 4571 length field.
997
         */
998
8
        tcp_framing_offset = 2;
999
8
    }
1000
1001
291
    msg_type     = tvb_get_ntohs(tvb, tcp_framing_offset + 0);
1002
291
    msg_length   = tvb_get_ntohs(tvb, tcp_framing_offset + 2);
1003
1004
    /* TURN ChannelData message ? */
1005
291
    if (msg_type & 0xC000) {
1006
        /* two first bits not NULL => should be a channel-data message */
1007
1008
        /*
1009
         * This is not heuristic, so we allow TURN Channel messages. Note
1010
         * RFC 9443 specifies that if it's not a known TURN server, then
1011
         * the packet could be QUIC instead.
1012
         */
1013
1014
        /* RFC 5764 defined a demultiplexing scheme to allow STUN to co-exist
1015
         * on the same 5-tuple as DTLS-SRTP (and ZRTP) by rejecting previously
1016
         * reserved channel numbers and method types, implicitly restricting
1017
         * channel numbers to 0x4000-0x7FFF.  RFC 5766 did not incorporate this
1018
         * restriction, instead indicating that reserved numbers MUST NOT be
1019
         * dropped.
1020
         * RFCs 7983, 8489, and 8656 reconciled this and formally indicated
1021
         * that channel numbers in the reserved range MUST be dropped, while
1022
         * further restricting the channel numbers to 0x4000-0x4FFF.
1023
         * Reject the range 0x8000-0xFFFF, except for the special
1024
         * MS-TURN multiplex channel number, since no implementation has
1025
         * used any other value in that range (that we know of).
1026
         */
1027
62
        if (msg_type & 0x8000 && msg_type != MS_MULTIPLEX_TURN) {
1028
            /* XXX: As this is not heuristic, if it is over UDP then
1029
             * the range 0x8000-0xBFFF is quite likely to be RTP/RTCP,
1030
             * and according to RFC 7983 should be forwarded to the RTP
1031
             * dissector. However, similar to TURN ChannelData, the heuristics
1032
             * for RTP are fairly weak and turned off by default over UDP.
1033
             * It would be nice to be able to ensure that for this packet
1034
             * the RTP over UDP heuristic dissector is called while still
1035
             * rejecting the packet and removing STUN from the list of layers.
1036
             */
1037
16
            return 0;
1038
16
        }
1039
1040
        /* "Over TCP and TLS-over-TCP, the ChannelData message MUST be padded to
1041
         * a multiple of 4 bytes (not reflected in the length field)... Over UDP,
1042
         * the padding is optional but MAY be included." - RFC 8656, 12.5
1043
         */
1044
46
        if (is_udp) {
1045
0
            if (reported_length != msg_length + CHANNEL_DATA_HDR_LEN &&
1046
0
                reported_length != ((msg_length + CHANNEL_DATA_HDR_LEN + 3) & ~0x3))
1047
0
                return 0;
1048
46
        } else { /* TCP */
1049
46
            if (reported_length != ((msg_length + CHANNEL_DATA_HDR_LEN + 3) & ~0x3))
1050
2
                return 0;
1051
46
        }
1052
1053
        /* XXX: why don't we invoke the turnchannel dissector instead? */
1054
44
        return dissect_stun_message_channel_data(tvb, pinfo, tree, msg_type, msg_length);
1055
46
    }
1056
1057
    /* Normal STUN message */
1058
229
    if (captured_length < STUN_HDR_LEN)
1059
4
        return 0;
1060
1061
225
    msg_type_class = ((msg_type & 0x0010) >> 4) | ((msg_type & 0x0100) >> 7) ;
1062
225
    msg_type_method = (msg_type & 0x000F) | ((msg_type & 0x00E0) >> 1) | ((msg_type & 0x3E00) >> 2);
1063
1064
225
    if (msg_type_method > 0x3FF) {
1065
        /* All values > 0xFF are "Reserved for DTLS-SRTP multiplexing collision
1066
         * avoidance, see RFC 7983. Cannot be made available for assignment
1067
         * without IETF Review."
1068
         *
1069
         * However, values of the first byte between 4 and 15 (corresponding with
1070
         * methods from 0x100 to 0x3FF) are not included in the multiplexing
1071
         * scheme and explicitly dropped in RFC 9443. Some of the higher values
1072
         * (notably 0x201, 0x202) are used by WhatsApp's implementation of STUN.
1073
         * (#20560). Since RFC 9443 recommends dropping the packet, and no
1074
         * other protocol as of yet has these values, if the 4-byte cookie is
1075
         * present that should be sufficient to call it STUN.
1076
         *
1077
         * If that is too generous, we could allow only the methods known to
1078
         * be used by WhatsApp.
1079
         */
1080
10
        return 0;
1081
10
    }
1082
1083
    /* Check if it is really a STUN message - reject messages without the
1084
     * RFC 5389 Magic and let the classicstun dissector handle those.
1085
     */
1086
215
    if ( tvb_get_ntohl(tvb, tcp_framing_offset + 4) != MESSAGE_COOKIE)
1087
132
        return 0;
1088
1089
    /* check if payload enough */
1090
83
    if (reported_length < (msg_length + STUN_HDR_LEN + tcp_framing_offset))
1091
1
        return 0;
1092
1093
    /* The message seems to be a valid STUN message! */
1094
1095
82
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "STUN");
1096
1097
    /* Create the transaction key which may be used
1098
       to track the conversation */
1099
82
    transaction_id[0] = tvb_get_ntohl(tvb, tcp_framing_offset + 8);
1100
82
    transaction_id[1] = tvb_get_ntohl(tvb, tcp_framing_offset + 12);
1101
82
    transaction_id[2] = tvb_get_ntohl(tvb, tcp_framing_offset + 16);
1102
1103
82
    transaction_id_key[0].length = 3;
1104
82
    transaction_id_key[0].key =  transaction_id;
1105
82
    transaction_id_key[1].length = 0;
1106
82
    transaction_id_key[1].key = NULL;
1107
1108
82
    switch (msg_type_method) {
1109
        /* if it's a TURN method, remember that */
1110
0
        case ALLOCATE:
1111
0
        case REFRESH:
1112
0
        case SEND:
1113
0
        case DATA_IND:
1114
0
        case CREATE_PERMISSION:
1115
0
        case CHANNELBIND:
1116
0
        case CONNECT:
1117
0
        case CONNECTION_BIND:
1118
0
        case CONNECTION_ATTEMPT:
1119
0
            is_turn = true;
1120
0
            break;
1121
82
    }
1122
1123
82
    conversation = find_or_create_conversation_strat(pinfo);
1124
1125
    /*
1126
     * Do we already have a state structure for this conv
1127
     */
1128
82
    stun_info = (stun_conv_info_t *)conversation_get_proto_data(conversation, proto_stun);
1129
82
    if (!stun_info) {
1130
        /* No.  Attach that information to the conversation, and add
1131
         * it to the list of information structures.
1132
         */
1133
21
        stun_info = wmem_new(wmem_file_scope(), stun_conv_info_t);
1134
21
        stun_info->transaction_pdus=wmem_tree_new(wmem_file_scope());
1135
21
        conversation_add_proto_data(conversation, proto_stun, stun_info);
1136
21
    }
1137
1138
82
    if (!pinfo->fd->visited) {
1139
82
        if ((stun_trans = (stun_transaction_t *)
1140
82
             wmem_tree_lookup32_array(stun_info->transaction_pdus,
1141
82
                                      transaction_id_key)) == NULL) {
1142
1143
44
            transaction_id_key[0].length = 3;
1144
44
            transaction_id_key[0].key =  transaction_id;
1145
44
            transaction_id_key[1].length = 0;
1146
44
            transaction_id_key[1].key = NULL;
1147
1148
44
            stun_trans=wmem_new(wmem_file_scope(), stun_transaction_t);
1149
44
            stun_trans->req_frame=0;
1150
44
            stun_trans->rep_frame=0;
1151
44
            stun_trans->req_time=pinfo->abs_ts;
1152
44
            wmem_tree_insert32_array(stun_info->transaction_pdus,
1153
44
                                     transaction_id_key,
1154
44
                                     (void *)stun_trans);
1155
44
        }
1156
1157
82
        if (msg_type_class == REQUEST) {
1158
            /* This is a request */
1159
42
            if (stun_trans->req_frame == 0) {
1160
30
                stun_trans->req_frame=pinfo->num;
1161
30
            }
1162
1163
42
        } else {
1164
            /* This is a catch-all for all non-request messages */
1165
40
            if (stun_trans->rep_frame == 0) {
1166
15
                stun_trans->rep_frame=pinfo->num;
1167
15
            }
1168
1169
40
        }
1170
82
    } else {
1171
0
        stun_trans=(stun_transaction_t *)wmem_tree_lookup32_array(stun_info->transaction_pdus,
1172
0
                                                                  transaction_id_key);
1173
0
    }
1174
1175
82
    if (!stun_trans) {
1176
        /* create a "fake" pana_trans structure */
1177
0
        stun_trans=wmem_new(pinfo->pool, stun_transaction_t);
1178
0
        stun_trans->req_frame=0;
1179
0
        stun_trans->rep_frame=0;
1180
0
        stun_trans->req_time=pinfo->abs_ts;
1181
0
    }
1182
1183
    /* According to [MS-TURN] section 2.2.2.8, the MAGIC_COOKIE attribute is
1184
     * the first attribute in all MS-TURN messages.
1185
     */
1186
82
    unsigned int first_attr_off = tcp_framing_offset + STUN_HDR_LEN;
1187
82
    if (tvb_get_ntohs(tvb, first_attr_off) == MAGIC_COOKIE &&
1188
0
        tvb_get_ntohl(tvb, first_attr_off + ATTR_HDR_LEN) == TURN_MAGIC_COOKIE) {
1189
0
        switch (msg_type) {
1190
0
        case MS_TURN_SEND:
1191
0
            msg_type_class = REQUEST;
1192
0
            msg_type_method = SEND;
1193
0
            break;
1194
0
        case MS_TURN_DATA_IND:
1195
0
            msg_type_class = INDICATION;
1196
0
            msg_type_method = DATA_IND;
1197
0
            break;
1198
0
        default:
1199
0
            break;
1200
0
        }
1201
0
    }
1202
1203
82
    msg_class_str  = val_to_str_const(msg_type_class, classes, "Unknown");
1204
82
    msg_method_str = val_to_str_const(msg_type_method, methods, "Unknown");
1205
1206
82
    col_add_lstr(pinfo->cinfo, COL_INFO,
1207
82
                 msg_method_str,
1208
82
                 " ",
1209
82
                 msg_class_str,
1210
82
                 COL_ADD_LSTR_TERMINATOR);
1211
1212
82
    offset = 0;
1213
82
    ti = proto_tree_add_item(tree, proto_stun, tvb, offset, -1, ENC_NA);
1214
1215
82
    stun_tree = proto_item_add_subtree(ti, ett_stun);
1216
1217
82
    if (msg_type_class == REQUEST) {
1218
20
        if (stun_trans->req_frame != pinfo->num) {
1219
5
            proto_item *it;
1220
5
            it=proto_tree_add_uint(stun_tree, hf_stun_duplicate,
1221
5
                                   tvb, offset, 0,
1222
5
                                   stun_trans->req_frame);
1223
5
            proto_item_set_generated(it);
1224
5
        }
1225
20
        if (stun_trans->rep_frame) {
1226
1
            proto_item *it;
1227
1
            it=proto_tree_add_uint(stun_tree, hf_stun_response_in,
1228
1
                                   tvb, offset, 0,
1229
1
                                   stun_trans->rep_frame);
1230
1
            proto_item_set_generated(it);
1231
1
        }
1232
20
    }
1233
62
    else {
1234
        /* Retransmission control */
1235
62
        if (stun_trans->rep_frame != pinfo->num) {
1236
2
            proto_item *it;
1237
2
            it=proto_tree_add_uint(stun_tree, hf_stun_duplicate,
1238
2
                                   tvb, offset, 0,
1239
2
                                   stun_trans->rep_frame);
1240
2
            proto_item_set_generated(it);
1241
2
        }
1242
62
        if (msg_type_class == SUCCESS_RESPONSE || msg_type_class == ERROR_RESPONSE) {
1243
            /* This is a response */
1244
7
            if (stun_trans->req_frame) {
1245
0
                proto_item *it;
1246
0
                nstime_t ns;
1247
1248
0
                it=proto_tree_add_uint(stun_tree, hf_stun_response_to, tvb,
1249
0
                                       offset, 0,
1250
0
                                       stun_trans->req_frame);
1251
0
                proto_item_set_generated(it);
1252
1253
0
                nstime_delta(&ns, &pinfo->abs_ts, &stun_trans->req_time);
1254
0
                it=proto_tree_add_time(stun_tree, hf_stun_time, tvb,
1255
0
                                       offset, 0, &ns);
1256
0
                proto_item_set_generated(it);
1257
0
            }
1258
1259
7
        }
1260
62
    }
1261
1262
82
    if (tcp_framing_offset) {
1263
6
        proto_tree_add_item(stun_tree, hf_stun_tcp_frame_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1264
6
        offset += 2;
1265
6
    }
1266
82
    ti = proto_tree_add_uint_format_value(stun_tree, hf_stun_type, tvb, offset, 2,
1267
82
                                          msg_type, "0x%04x (%s %s)", msg_type, msg_method_str, msg_class_str);
1268
82
    stun_type_tree = proto_item_add_subtree(ti, ett_stun_type);
1269
82
    ti = proto_tree_add_uint(stun_type_tree, hf_stun_type_class, tvb, offset, 2, msg_type);
1270
82
    proto_item_append_text(ti, " %s (%d)", msg_class_str, msg_type_class);
1271
82
    ti = proto_tree_add_uint(stun_type_tree, hf_stun_type_method, tvb, offset, 2, msg_type);
1272
82
    proto_item_append_text(ti, " %s (0x%03x)", msg_method_str, msg_type_method);
1273
82
    proto_tree_add_uint(stun_type_tree, hf_stun_type_method_assignment, tvb, offset, 2, msg_type);
1274
82
    offset += 2;
1275
1276
82
    ti_length = proto_tree_add_item(stun_tree, hf_stun_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1277
82
    offset += 2;
1278
82
    proto_tree_add_item(stun_tree, hf_stun_cookie, tvb, offset, 4, ENC_NA);
1279
82
    offset += 4;
1280
82
    proto_tree_add_item(stun_tree, hf_stun_id, tvb, offset, 12, ENC_NA);
1281
82
    offset += 12;
1282
1283
    /* Remember this (in host order) so we can show clear xor'd addresses */
1284
82
    magic_cookie_first_word = tvb_get_ntohl(tvb, tcp_framing_offset + 4);
1285
1286
82
    if (msg_length != 0) {
1287
22
        const char        *attribute_name_str;
1288
1289
22
        if (stun_network_version == NET_VER_AUTO) {
1290
            /* According to [MS-TURN] section 2.2.2.8: "This attribute MUST be the
1291
               first attribute following the TURN message header in all TURN messages" */
1292
0
            if (offset < (STUN_HDR_LEN + msg_length) &&
1293
0
                tvb_get_ntohs(tvb, offset) == MAGIC_COOKIE) {
1294
0
              network_version = NET_VER_MS_TURN;
1295
0
            } else if (msg_length & 3) {
1296
              /* Starting with RFC 5389 msg_length MUST be a multiple of 4 bytes */
1297
0
              network_version = NET_VER_3489;
1298
0
            } else {
1299
0
              network_version = NET_VER_5389;
1300
0
            }
1301
22
        } else {
1302
22
            network_version = stun_network_version;
1303
            /* Starting with RFC 5389 msg_length MUST be multiple of 4 bytes */
1304
22
            if ((network_version >= NET_VER_5389 && msg_length & 3) != 0)
1305
0
                expert_add_info(pinfo, ti_length, &ei_stun_wrong_msglen);
1306
22
        }
1307
1308
22
        ti = proto_tree_add_uint(stun_tree, hf_stun_network_version, tvb, offset, 0, network_version);
1309
22
        proto_item_set_generated(ti);
1310
1311
22
        ti = proto_tree_add_item(stun_tree, hf_stun_attributes, tvb, offset, msg_length, ENC_NA);
1312
22
        att_all_tree = proto_item_add_subtree(ti, ett_stun_att_all);
1313
1314
178
        while (offset < (STUN_HDR_LEN + msg_length)) {
1315
177
            att_type = tvb_get_ntohs(tvb, offset);     /* Attribute type field in attribute header */
1316
177
            att_length = tvb_get_ntohs(tvb, offset+2); /* Attribute length field in attribute header */
1317
177
            if (network_version >= NET_VER_5389)
1318
169
                att_length_pad = WS_ROUNDUP_4(att_length); /* Attribute length including padding */
1319
8
            else
1320
8
                att_length_pad = att_length;
1321
177
            att_type_display = att_type;
1322
            /* Early drafts and MS-TURN use swapped numbers to later versions */
1323
177
            if ((network_version < NET_VER_3489) && (att_type == 0x0014 || att_type == 0x0015)) {
1324
0
                att_type_display ^= 1;
1325
0
            }
1326
177
            attribute_name_str = try_val_to_str_ext(att_type_display, &attributes_ext);
1327
177
            if (attribute_name_str){
1328
33
                ti = proto_tree_add_uint_format(att_all_tree, hf_stun_attr,
1329
33
                                                tvb, offset, ATTR_HDR_LEN+att_length_pad,
1330
33
                                                att_type, "%s", attribute_name_str);
1331
33
                att_tree = proto_item_add_subtree(ti, ett_stun_att);
1332
33
                ti = proto_tree_add_uint_format_value(att_tree, hf_stun_att_type, tvb,
1333
33
                                         offset, 2, att_type, "%s", attribute_name_str);
1334
33
                att_type_tree = proto_item_add_subtree(ti, ett_stun_att_type);
1335
33
                proto_tree_add_uint(att_type_tree, hf_stun_att_type_comprehension, tvb, offset, 2, att_type);
1336
33
                proto_tree_add_uint(att_type_tree, hf_stun_att_type_assignment, tvb, offset, 2, att_type);
1337
1338
33
                if ((offset+ATTR_HDR_LEN+att_length_pad) > (STUN_HDR_LEN+msg_length+tcp_framing_offset)) {
1339
0
                    proto_tree_add_uint_format_value(att_tree,
1340
0
                                                     hf_stun_att_length, tvb, offset+2, 2,
1341
0
                                                     att_length_pad,
1342
0
                                                     "%u (bogus, goes past the end of the message)",
1343
0
                                                     att_length_pad);
1344
0
                    break;
1345
0
                }
1346
144
            } else {
1347
144
                att_tree = proto_tree_add_expert_format(att_all_tree, pinfo, &ei_stun_unknown_attribute, tvb,
1348
144
                                                        offset, ATTR_HDR_LEN + att_length_pad, "Unknown attribute 0x%04x", att_type_display);
1349
144
                proto_tree_add_uint_format_value(att_tree, hf_stun_att_type, tvb,
1350
144
                                                 offset, 2, att_type, "0x%04x", att_type_display);
1351
144
            }
1352
177
            offset += 2;
1353
1354
177
            proto_tree_add_uint(att_tree, hf_stun_att_length, tvb,
1355
177
                                offset, 2, att_length);
1356
177
            offset += 2;
1357
1358
            /* Zero out address */
1359
177
            clear_address(&addr);
1360
1361
177
            switch (att_type_display) {
1362
1363
                /* Deprecated STUN RFC3489 attributes */
1364
4
            case RESPONSE_ADDRESS:
1365
5
            case SOURCE_ADDRESS:
1366
5
            case CHANGED_ADDRESS:
1367
5
            case REFLECTED_FROM:
1368
5
            case DESTINATION_ADDRESS:
1369
5
                if (att_length < 1)
1370
3
                    break;
1371
2
                proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset, 1, ENC_NA);
1372
2
                if (att_length < 2)
1373
0
                    break;
1374
2
                proto_tree_add_item(att_tree, hf_stun_att_family, tvb, offset+1, 1, ENC_BIG_ENDIAN);
1375
2
                if (att_length < 4)
1376
1
                    break;
1377
1
                proto_tree_add_item(att_tree, hf_stun_att_port, tvb, offset+2, 2, ENC_BIG_ENDIAN);
1378
1
                switch (tvb_get_uint8(tvb, offset+1))
1379
1
                {
1380
1
                case 1:
1381
1
                    if (att_length < 8)
1382
0
                        break;
1383
1
                    proto_tree_add_item(att_tree, hf_stun_att_ipv4, tvb, offset+4, 4, ENC_BIG_ENDIAN);
1384
1
                    proto_item_append_text(att_tree, " (Deprecated): %s:%d", tvb_ip_to_str(pinfo->pool, tvb, offset+4),tvb_get_ntohs(tvb,offset+2));
1385
1386
1
                    break;
1387
1388
0
                case 2:
1389
0
                    if (att_length < 20)
1390
0
                        break;
1391
0
                    proto_tree_add_item(att_tree, hf_stun_att_ipv6, tvb, offset+4, 16, ENC_NA);
1392
0
                    break;
1393
1
                }
1394
1
                break;
1395
1396
                /* Deprecated STUN RFC3489 attributes */
1397
1
            case PASSWORD:
1398
1
                {
1399
1
                proto_tree_add_item(att_tree, hf_stun_att_password, tvb, offset, att_length, ENC_NA);
1400
1
                }
1401
1
                break;
1402
1403
3
            case MAPPED_ADDRESS:
1404
3
            case ALTERNATE_SERVER:
1405
3
            case RESPONSE_ORIGIN:
1406
3
            case OTHER_ADDRESS:
1407
3
            case MS_ALT_MAPPED_ADDRESS:
1408
4
            case MS_ALTERNATE_SERVER:
1409
4
            {
1410
4
                const char        *addr_str = NULL;
1411
4
                uint16_t           att_port;
1412
1413
4
                if (att_length < 1)
1414
1
                    break;
1415
3
                proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset, 1, ENC_NA);
1416
3
                if (att_length < 2)
1417
0
                    break;
1418
3
                proto_tree_add_item(att_tree, hf_stun_att_family, tvb, offset+1, 1, ENC_BIG_ENDIAN);
1419
3
                if (att_length < 4)
1420
0
                    break;
1421
3
                proto_tree_add_item_ret_uint16(att_tree, hf_stun_att_port, tvb, offset+2, 2, ENC_BIG_ENDIAN, &att_port);
1422
1423
3
                switch (tvb_get_uint8(tvb, offset+1)) {
1424
0
                case 1:
1425
0
                    if (att_length < 8)
1426
0
                        break;
1427
0
                    addr_str = tvb_ip_to_str(pinfo->pool, tvb, offset + 4);
1428
0
                    proto_tree_add_item(att_tree, hf_stun_att_ipv4, tvb, offset+4, 4, ENC_BIG_ENDIAN);
1429
0
                    break;
1430
1431
0
                case 2:
1432
0
                    if (att_length < 20)
1433
0
                        break;
1434
0
                    addr_str = tvb_ip6_to_str(pinfo->pool, tvb, offset + 4);
1435
0
                    proto_tree_add_item(att_tree, hf_stun_att_ipv6, tvb, offset+4, 16, ENC_NA);
1436
0
                    break;
1437
3
                }
1438
1439
3
                if (addr_str != NULL) {
1440
0
                    proto_item_append_text(att_tree, ": %s:%d", addr_str, att_port);
1441
0
                    col_append_fstr(pinfo->cinfo, COL_INFO, " %s: %s:%d",
1442
0
                                    attribute_name_str, addr_str, att_port);
1443
0
                }
1444
1445
3
                break;
1446
3
            }
1447
5
            case CHANGE_REQUEST:
1448
5
            {
1449
5
                bool change_ip, change_port;
1450
5
                if (att_length < 4)
1451
2
                    break;
1452
3
                proto_tree_add_item_ret_boolean(att_tree, hf_stun_att_change_ip, tvb, offset, 4, ENC_BIG_ENDIAN, &change_ip);
1453
3
                proto_tree_add_item_ret_boolean(att_tree, hf_stun_att_change_port, tvb, offset, 4, ENC_BIG_ENDIAN, &change_port);
1454
3
                if (change_ip && change_port) {
1455
1
                    col_append_str(pinfo->cinfo, COL_INFO, ", Change IP and Port");
1456
2
                } else if (change_ip) {
1457
1
                    col_append_str(pinfo->cinfo, COL_INFO, ", Change IP");
1458
1
                } else if (change_port) {
1459
0
                    col_append_str(pinfo->cinfo, COL_INFO, ", Change Port");
1460
0
                }
1461
3
                break;
1462
5
            }
1463
1
            case USERNAME:
1464
1
            {
1465
1
                if (network_version >  NET_VER_3489) {
1466
1
                    const uint8_t *user_name_str;
1467
1468
1
                    proto_tree_add_item_ret_string(att_tree, hf_stun_att_username, tvb, offset, att_length, ENC_UTF_8|ENC_NA, pinfo->pool, &user_name_str);
1469
1
                    proto_item_append_text(att_tree, ": %s", user_name_str);
1470
1
                    col_append_fstr( pinfo->cinfo, COL_INFO, " user: %s", user_name_str);
1471
1
                } else {
1472
0
                    proto_tree_add_item(att_tree, hf_stun_att_username_opaque, tvb, offset, att_length, ENC_NA);
1473
0
                }
1474
1
                break;
1475
5
            }
1476
3
            case MESSAGE_INTEGRITY:
1477
3
                if (att_length < 20)
1478
2
                    break;
1479
1
                proto_tree_add_item(att_tree, hf_stun_att_hmac, tvb, offset, att_length, ENC_NA);
1480
1
                break;
1481
1482
0
            case ERROR_CODE:
1483
0
                if (att_length < 2)
1484
0
                    break;
1485
0
                proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset, 2, ENC_NA);
1486
0
                if (att_length < 3)
1487
0
                    break;
1488
0
                proto_tree_add_item(att_tree, hf_stun_att_error_class, tvb, offset+2, 1, ENC_BIG_ENDIAN);
1489
0
                if (att_length < 4)
1490
0
                    break;
1491
0
                proto_tree_add_item(att_tree, hf_stun_att_error_number, tvb, offset+3, 1, ENC_BIG_ENDIAN);
1492
0
                {
1493
0
                    int           human_error_num = tvb_get_uint8(tvb, offset+2) * 100 + tvb_get_uint8(tvb, offset+3);
1494
0
                    const char   *error_str = val_to_str_ext_const(human_error_num, &error_code_ext, "*Unknown error code*");
1495
0
                    proto_item_append_text(
1496
0
                        att_tree,
1497
0
                        " %d (%s)",
1498
0
                        human_error_num, /* human readable error code */
1499
0
                        error_str
1500
0
                        );
1501
0
                    col_append_fstr(
1502
0
                        pinfo->cinfo, COL_INFO,
1503
0
                        " error-code: %d (%s)",
1504
0
                        human_error_num,
1505
0
                        error_str
1506
0
                        );
1507
0
                }
1508
0
                if (att_length < 5)
1509
0
                    break;
1510
0
                {
1511
0
                const uint8_t *error_reas_str;
1512
0
                proto_tree_add_item_ret_string(att_tree, hf_stun_att_error_reason, tvb, offset + 4, att_length - 4, ENC_UTF_8 | ENC_NA, pinfo->pool, &error_reas_str);
1513
1514
0
                proto_item_append_text(att_tree, ": %s", error_reas_str);
1515
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " %s", error_reas_str);
1516
0
                }
1517
0
                break;
1518
1519
3
            case UNKNOWN_ATTRIBUTES:
1520
26
                for (i = 0; i < att_length; i += 2)
1521
23
                    proto_tree_add_item(att_tree, hf_stun_att_unknown, tvb, offset+i, 2, ENC_BIG_ENDIAN);
1522
3
                break;
1523
1524
0
            case REALM:
1525
0
            {
1526
0
                const uint8_t *realm_str;
1527
0
                proto_tree_add_item_ret_string(att_tree, hf_stun_att_realm, tvb, offset, att_length, ENC_UTF_8|ENC_NA, pinfo->pool, &realm_str);
1528
0
                proto_item_append_text(att_tree, ": %s", realm_str);
1529
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " realm: %s", realm_str);
1530
0
                break;
1531
0
            }
1532
1
            case NONCE:
1533
1
            {
1534
1
                const uint8_t *nonce_str;
1535
1
                proto_tree_add_item_ret_string(att_tree, hf_stun_att_nonce, tvb, offset, att_length, ENC_UTF_8|ENC_NA, pinfo->pool, &nonce_str);
1536
1
                proto_item_append_text(att_tree, ": %s", nonce_str);
1537
1
                col_append_str(pinfo->cinfo, COL_INFO, " with nonce");
1538
1
                break;
1539
0
            }
1540
0
            case PASSWORD_ALGORITHM:
1541
0
            case PASSWORD_ALGORITHMS:
1542
0
            {
1543
0
                unsigned alg, alg_param_len, alg_param_len_pad;
1544
0
                unsigned remaining = att_length;
1545
0
                while (remaining > 0) {
1546
0
                   unsigned loopoffset = offset + att_length - remaining;
1547
0
                   if (remaining < 4) {
1548
0
                       proto_tree_add_expert_format(att_tree, pinfo, &ei_stun_short_packet, tvb,
1549
0
                           loopoffset, remaining, "Too few bytes left for TLV header (%d < 4)", remaining);
1550
0
                       break;
1551
0
                   }
1552
0
                   proto_tree_add_item_ret_uint(att_tree, hf_stun_att_pw_alg, tvb, loopoffset, 2, ENC_BIG_ENDIAN, &alg);
1553
0
                   proto_tree_add_item_ret_uint(att_tree, hf_stun_att_pw_alg_param_len, tvb, loopoffset+2, 2, ENC_BIG_ENDIAN, &alg_param_len);
1554
0
                   if (alg_param_len > 0) {
1555
0
                       if (alg_param_len+4 >= remaining)
1556
0
                           proto_tree_add_item(att_tree, hf_stun_att_pw_alg_param_data, tvb, loopoffset+4, alg_param_len, ENC_NA);
1557
0
                       else {
1558
0
                           proto_tree_add_expert_format(att_tree, pinfo, &ei_stun_short_packet, tvb,
1559
0
                                loopoffset, remaining, "Too few bytes left for parameter data (%u < %u)", remaining-4, alg_param_len);
1560
0
                           break;
1561
0
                       }
1562
0
                   }
1563
                   /* Hopefully, in case MS-TURN ever gets PASSWORD-ALGORITHM(S) support they will add it with padding */
1564
0
                   alg_param_len_pad = WS_ROUNDUP_4(alg_param_len);
1565
1566
0
                   if (alg_param_len < alg_param_len_pad)
1567
0
                       proto_tree_add_uint(att_tree, hf_stun_att_padding, tvb, loopoffset+alg_param_len, alg_param_len_pad-alg_param_len, alg_param_len_pad-alg_param_len);
1568
0
                   remaining -= (alg_param_len_pad + 4);
1569
0
                   if ((att_type_display == PASSWORD_ALGORITHM) && (remaining > 0)) {
1570
0
                       proto_tree_add_expert_format(att_tree, pinfo, &ei_stun_long_attribute, tvb,
1571
0
                           loopoffset, remaining, " (PASSWORD-ALGORITHM)");
1572
                       /* Continue anyway */
1573
0
                   }
1574
0
                }
1575
0
                break;
1576
0
            }
1577
0
            case XOR_PEER_ADDRESS:
1578
0
            case XOR_RELAYED_ADDRESS:
1579
0
                found_turn_attributes = true;
1580
                /* Fallthrough */
1581
0
            case XOR_MAPPED_ADDRESS:
1582
1
            case XOR_RESPONSE_TARGET:
1583
2
            case XOR_REFLECTED_FROM:
1584
2
            case MS_XOR_MAPPED_ADDRESS:
1585
2
            case REMOTE_SITE_ADDR:
1586
2
            case REMOTE_RELAY_SITE:
1587
2
            case LOCAL_SITE_ADDR:
1588
2
            case LOCAL_RELAY_SITE:
1589
2
                if (att_length < 1)
1590
1
                    break;
1591
1
                proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset, 1, ENC_NA);
1592
1
                if (att_length < 2)
1593
0
                    break;
1594
1
                proto_tree_add_item(att_tree, hf_stun_att_family, tvb, offset+1, 1, ENC_BIG_ENDIAN);
1595
1
                if (att_length < 4)
1596
0
                    break;
1597
1
                proto_tree_add_item(att_tree, hf_stun_att_xor_port, tvb, offset+2, 2, ENC_NA);
1598
1599
                /* Show the port 'in the clear'
1600
                   XOR (host order) transid with (host order) xor-port.
1601
                   Add host-order port into tree. */
1602
1
                clear_port = tvb_get_ntohs(tvb, offset+2) ^ (magic_cookie_first_word >> 16);
1603
1
                ti = proto_tree_add_uint(att_tree, hf_stun_att_port, tvb, offset+2, 2, clear_port);
1604
1
                proto_item_set_generated(ti);
1605
1606
1
                if (att_length < 8)
1607
0
                    break;
1608
1609
1
                switch (tvb_get_uint8(tvb, offset+1)) {
1610
0
                case 1:
1611
0
                    proto_tree_add_item(att_tree, hf_stun_att_xor_ipv4, tvb, offset+4, 4, ENC_NA);
1612
1613
                    /* Show the address 'in the clear'.
1614
                       XOR (host order) transid with (host order) xor-address.
1615
                       Add in network order tree. */
1616
0
                    clear_ip[0] = tvb_get_ipv4(tvb, offset+4) ^ g_htonl(magic_cookie_first_word);
1617
0
                    ti = proto_tree_add_ipv4(att_tree, hf_stun_att_ipv4, tvb, offset+4, 4, clear_ip[0]);
1618
0
                    proto_item_set_generated(ti);
1619
1620
0
                    set_address(&addr, AT_IPv4, 4, clear_ip);
1621
0
                    break;
1622
1623
0
                case 2:
1624
0
                    if (att_length < 20)
1625
0
                        break;
1626
1627
0
                    proto_tree_add_item(att_tree, hf_stun_att_xor_ipv6, tvb, offset+4, 16, ENC_NA);
1628
1629
0
                    tvb_get_ipv6(tvb, offset+4, (ws_in6_addr *)clear_ip);
1630
0
                    clear_ip[0] ^= g_htonl(magic_cookie_first_word);
1631
0
                    clear_ip[1] ^= g_htonl(transaction_id[0]);
1632
0
                    clear_ip[2] ^= g_htonl(transaction_id[1]);
1633
0
                    clear_ip[3] ^= g_htonl(transaction_id[2]);
1634
0
                    ti = proto_tree_add_ipv6(att_tree, hf_stun_att_ipv6, tvb, offset+4, 16,
1635
0
                                             (const ws_in6_addr *)clear_ip);
1636
0
                    proto_item_set_generated(ti);
1637
1638
0
                    set_address(&addr, AT_IPv6, 16, &clear_ip);
1639
0
                    break;
1640
1641
1
                default:
1642
1
                    clear_address(&addr);
1643
1
                    break;
1644
1
                }
1645
1646
1
                if (addr.type != AT_NONE) {
1647
0
                    const char *ipstr = address_to_str(pinfo->pool, &addr);
1648
0
                    proto_item_append_text(att_tree, ": %s:%d", ipstr, clear_port);
1649
0
                    col_append_fstr(pinfo->cinfo, COL_INFO, " %s: %s:%d",
1650
0
                                    attribute_name_str, ipstr, clear_port);
1651
0
                }
1652
1653
1
                break;
1654
1655
0
            case REQUESTED_ADDRESS_FAMILY:
1656
0
                if (att_length < 1)
1657
0
                    break;
1658
0
                proto_tree_add_item(att_tree, hf_stun_att_family, tvb, offset, 1, ENC_BIG_ENDIAN);
1659
0
                if (att_length < 4)
1660
0
                    break;
1661
0
                proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset+1, 3, ENC_NA);
1662
0
                break;
1663
6
            case EVEN_PORT:
1664
6
                if (att_length < 1)
1665
5
                    break;
1666
1
                proto_tree_add_item(att_tree, hf_stun_att_reserve_next, tvb, offset, 1, ENC_BIG_ENDIAN);
1667
1
                found_turn_attributes = true;
1668
1
                break;
1669
1670
0
            case RESERVATION_TOKEN:
1671
0
                if (att_length < 8)
1672
0
                    break;
1673
0
                proto_tree_add_item(att_tree, hf_stun_att_token, tvb, offset, 8, ENC_NA);
1674
0
                found_turn_attributes = true;
1675
0
                break;
1676
1677
0
            case PRIORITY:
1678
0
                if (att_length < 4)
1679
0
                    break;
1680
0
                proto_tree_add_item(att_tree, hf_stun_att_priority, tvb, offset, 4, ENC_BIG_ENDIAN);
1681
0
                break;
1682
1683
0
            case PADDING:
1684
0
                proto_tree_add_uint(att_tree, hf_stun_att_padding, tvb, offset, att_length, att_length);
1685
0
                break;
1686
1687
1
            case LEGACY_ICMP:
1688
1
            case ICMP:
1689
1
                if (att_length < 4)
1690
1
                    break;
1691
0
                proto_tree_add_item(att_tree, hf_stun_att_icmp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1692
0
                proto_tree_add_item(att_tree, hf_stun_att_icmp_code, tvb, offset+1, 1, ENC_BIG_ENDIAN);
1693
0
                break;
1694
1695
0
            case MS_TURN_UNKNOWN_8006:
1696
0
                proto_tree_add_item(att_tree, hf_stun_att_ms_turn_unknown_8006, tvb, offset, att_length, ENC_NA);
1697
0
                break;
1698
1699
0
            case SOFTWARE:
1700
0
                proto_tree_add_item(att_tree, hf_stun_att_software, tvb, offset, att_length, ENC_UTF_8);
1701
0
                break;
1702
1703
0
            case CACHE_TIMEOUT:
1704
0
                if (att_length < 4)
1705
0
                    break;
1706
0
                proto_tree_add_item(att_tree, hf_stun_att_cache_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
1707
0
                break;
1708
1709
0
            case FINGERPRINT:
1710
0
                if (att_length < 4)
1711
0
                    break;
1712
0
                proto_tree_add_checksum(att_tree, tvb, offset, hf_stun_att_crc32, hf_stun_att_crc32_status, &ei_stun_fingerprint_bad, pinfo, crc32_ccitt_tvb_offset(tvb, tcp_framing_offset, offset-4-tcp_framing_offset) ^ 0x5354554e, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
1713
0
                break;
1714
1715
0
            case ICE_CONTROLLED:
1716
0
            case ICE_CONTROLLING:
1717
0
                if (att_length < 8)
1718
0
                    break;
1719
0
                proto_tree_add_item(att_tree, hf_stun_att_tie_breaker, tvb, offset, 8, ENC_NA);
1720
0
                break;
1721
1722
0
            case DATA:
1723
0
                if (att_length > 0) {
1724
0
                    tvbuff_t *next_tvb;
1725
0
                    proto_tree_add_item(att_tree, hf_stun_att_value, tvb, offset, att_length, ENC_NA);
1726
1727
0
                    next_tvb = tvb_new_subset_length(tvb, offset, att_length);
1728
1729
0
                    if (!dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, att_tree, &hdtbl_entry, NULL)) {
1730
0
                        call_dissector_only(data_handle, next_tvb, pinfo, att_tree, NULL);
1731
0
                    }
1732
1733
0
                }
1734
0
                found_turn_attributes = true;
1735
0
                break;
1736
1737
0
            case REQUESTED_TRANSPORT:
1738
0
                if (att_length < 1)
1739
0
                    break;
1740
0
                proto_tree_add_item(att_tree, hf_stun_att_transp, tvb, offset, 1, ENC_BIG_ENDIAN);
1741
0
                if (att_length < 4)
1742
0
                    break;
1743
1744
0
                {
1745
0
                    uint8_t protoCode = tvb_get_uint8(tvb, offset);
1746
0
                    const char *protoCode_str = val_to_str(pinfo->pool, protoCode, transportnames, "Unknown (0x%8x)");
1747
1748
0
                    proto_item_append_text(att_tree, ": %s", protoCode_str);
1749
0
                    col_append_fstr(
1750
0
                        pinfo->cinfo, COL_INFO,
1751
0
                        " %s",
1752
0
                        protoCode_str
1753
0
                        );
1754
0
                }
1755
0
                proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset+1, 3, ENC_NA);
1756
0
                found_turn_attributes = true;
1757
0
                break;
1758
1759
0
            case CHANNEL_NUMBER:
1760
0
                if (att_length < 4)
1761
0
                    break;
1762
0
                proto_tree_add_item(att_tree, hf_stun_att_channelnum, tvb, offset, 2, ENC_BIG_ENDIAN);
1763
0
                {
1764
0
                    uint16_t chan = tvb_get_ntohs(tvb, offset);
1765
0
                    proto_item_append_text(att_tree, ": 0x%x", chan);
1766
0
                    col_append_fstr(
1767
0
                        pinfo->cinfo, COL_INFO,
1768
0
                        " ChannelNumber=0x%x",
1769
0
                        chan
1770
0
                        );
1771
0
                }
1772
0
                proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset+2, 2, ENC_NA);
1773
0
                found_turn_attributes = true;
1774
0
                break;
1775
1776
0
            case MAGIC_COOKIE:
1777
0
                if (att_length < 4)
1778
0
                    break;
1779
0
                proto_tree_add_item(att_tree, hf_stun_att_magic_cookie, tvb, offset, 4, ENC_BIG_ENDIAN);
1780
0
                break;
1781
1782
1
            case BANDWIDTH:
1783
1
                if (att_length < 4)
1784
0
                    break;
1785
1
                proto_tree_add_item(att_tree, hf_stun_att_bandwidth, tvb, offset, 4, ENC_BIG_ENDIAN);
1786
1
                proto_item_append_text(att_tree, " %d", tvb_get_ntohl(tvb, offset));
1787
1
                col_append_fstr(
1788
1
                    pinfo->cinfo, COL_INFO,
1789
1
                    " bandwidth: %d",
1790
1
                    tvb_get_ntohl(tvb, offset)
1791
1
                    );
1792
1
                found_turn_attributes = true;
1793
1
                break;
1794
0
            case LIFETIME:
1795
0
                if (att_length < 4)
1796
0
                    break;
1797
0
                proto_tree_add_item(att_tree, hf_stun_att_lifetime, tvb, offset, 4, ENC_BIG_ENDIAN);
1798
0
                proto_item_append_text(att_tree, " %d", tvb_get_ntohl(tvb, offset));
1799
0
                col_append_fstr(
1800
0
                    pinfo->cinfo, COL_INFO,
1801
0
                    " lifetime: %d",
1802
0
                    tvb_get_ntohl(tvb, offset)
1803
0
                    );
1804
0
                found_turn_attributes = true;
1805
0
                break;
1806
1807
0
            case MS_VERSION:
1808
0
                proto_tree_add_item(att_tree, hf_stun_att_ms_version, tvb, offset, 4, ENC_BIG_ENDIAN);
1809
0
                proto_item_append_text(att_tree, ": %s", val_to_str(pinfo->pool, tvb_get_ntohl(tvb, offset), ms_version_vals, "Unknown (0x%u)"));
1810
0
                break;
1811
0
            case MS_IMPLEMENTATION_VER:
1812
0
                proto_tree_add_item(att_tree, hf_stun_att_ms_version_ice, tvb, offset, 4, ENC_BIG_ENDIAN);
1813
0
                proto_item_append_text(att_tree, ": %s", rval_to_str_wmem(pinfo->pool, tvb_get_ntohl(tvb, offset), ms_version_ice_rvals, "Unknown (0x%u)"));
1814
0
                break;
1815
0
            case MS_SEQUENCE_NUMBER:
1816
0
                proto_tree_add_item(att_tree, hf_stun_att_ms_connection_id, tvb, offset, 20, ENC_NA);
1817
0
                proto_tree_add_item(att_tree, hf_stun_att_ms_sequence_number, tvb, offset+20, 4, ENC_BIG_ENDIAN);
1818
0
                break;
1819
0
            case MS_SERVICE_QUALITY:
1820
0
                proto_tree_add_item(att_tree, hf_stun_att_ms_stream_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1821
0
                proto_tree_add_item(att_tree, hf_stun_att_ms_service_quality, tvb, offset+2, 2, ENC_BIG_ENDIAN);
1822
0
                break;
1823
0
            case BANDWIDTH_ACM:
1824
0
                proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset, 2, ENC_NA);
1825
0
                proto_tree_add_item(att_tree, hf_stun_att_bandwidth_acm_type, tvb, offset+2, 2, ENC_BIG_ENDIAN);
1826
0
                break;
1827
0
            case BANDWIDTH_RSV_ID:
1828
0
                proto_tree_add_item(att_tree, hf_stun_att_bandwidth_rsv_id, tvb, offset, 16, ENC_NA);
1829
0
                break;
1830
0
            case BANDWIDTH_RSV_AMOUNT:
1831
0
                proto_tree_add_item(att_tree, hf_stun_att_bandwidth_rsv_amount_masb, tvb, offset, 4, ENC_BIG_ENDIAN);
1832
0
                proto_tree_add_item(att_tree, hf_stun_att_bandwidth_rsv_amount_misb, tvb, offset+4, 4, ENC_BIG_ENDIAN);
1833
0
                proto_tree_add_item(att_tree, hf_stun_att_bandwidth_rsv_amount_marb, tvb, offset+8, 4, ENC_BIG_ENDIAN);
1834
0
                proto_tree_add_item(att_tree, hf_stun_att_bandwidth_rsv_amount_mirb, tvb, offset+12, 4, ENC_BIG_ENDIAN);
1835
0
                break;
1836
0
            case REMOTE_SITE_ADDR_RP:
1837
0
            case LOCAL_SITE_ADDR_RP:
1838
0
                proto_tree_add_item(att_tree, hf_stun_att_address_rp_a, tvb, offset, 4, ENC_BIG_ENDIAN);
1839
0
                proto_tree_add_item(att_tree, hf_stun_att_address_rp_b, tvb, offset, 4, ENC_BIG_ENDIAN);
1840
0
                proto_tree_add_item(att_tree, hf_stun_att_address_rp_rsv1, tvb, offset, 4, ENC_BIG_ENDIAN);
1841
0
                proto_tree_add_item(att_tree, hf_stun_att_address_rp_masb, tvb, offset+4, 4, ENC_BIG_ENDIAN);
1842
0
                proto_tree_add_item(att_tree, hf_stun_att_address_rp_marb, tvb, offset+8, 4, ENC_BIG_ENDIAN);
1843
0
                break;
1844
0
            case REMOTE_RELAY_SITE_RP:
1845
0
            case LOCAL_RELAY_SITE_RP:
1846
0
                proto_tree_add_item(att_tree, hf_stun_att_address_rp_a, tvb, offset, 4, ENC_BIG_ENDIAN);
1847
0
                proto_tree_add_item(att_tree, hf_stun_att_address_rp_rsv2, tvb, offset, 4, ENC_BIG_ENDIAN);
1848
0
                proto_tree_add_item(att_tree, hf_stun_att_address_rp_masb, tvb, offset+4, 4, ENC_BIG_ENDIAN);
1849
0
                proto_tree_add_item(att_tree, hf_stun_att_address_rp_marb, tvb, offset+8, 4, ENC_BIG_ENDIAN);
1850
0
                break;
1851
0
            case SIP_DIALOG_ID:
1852
0
                proto_tree_add_item(att_tree, hf_stun_att_sip_dialog_id, tvb, offset, att_length, ENC_NA);
1853
0
                break;
1854
0
            case SIP_CALL_ID:
1855
0
                proto_tree_add_item(att_tree, hf_stun_att_sip_call_id, tvb, offset, att_length, ENC_NA);
1856
0
                break;
1857
0
            case LOCATION_PROFILE:
1858
0
                proto_tree_add_item(att_tree, hf_stun_att_lp_peer_location, tvb, offset, 1, ENC_BIG_ENDIAN);
1859
0
                proto_tree_add_item(att_tree, hf_stun_att_lp_self_location, tvb, offset+1, 1, ENC_BIG_ENDIAN);
1860
0
                proto_tree_add_item(att_tree, hf_stun_att_lp_federation, tvb, offset+2, 1, ENC_BIG_ENDIAN);
1861
0
                proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset+3, 1, ENC_NA);
1862
0
                break;
1863
0
            case MS_CANDIDATE_IDENTIFIER:
1864
0
                proto_tree_add_item(att_tree, hf_stun_att_ms_foundation, tvb, offset, 4, ENC_ASCII);
1865
0
                break;
1866
0
            case MS_MULTIPLEXED_TURN_SESSION_ID:
1867
0
                proto_tree_add_item(att_tree, hf_stun_att_ms_multiplexed_turn_session_id, tvb, offset, 8, ENC_BIG_ENDIAN);
1868
                /* Trick to force decoding of MS-TURN Multiplexed TURN channels */
1869
0
                found_turn_attributes = true;
1870
0
                break;
1871
1872
0
            case GOOG_NETWORK_INFO:
1873
0
                proto_tree_add_item(att_tree, hf_stun_att_google_network_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1874
0
                proto_tree_add_item(att_tree, hf_stun_att_google_network_cost, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
1875
0
                break;
1876
1877
127
            default:
1878
127
                if (att_length > 0)
1879
26
                    proto_tree_add_item(att_tree, hf_stun_att_value, tvb, offset, att_length, ENC_NA);
1880
127
                break;
1881
177
            }
1882
1883
156
            if ((network_version >= NET_VER_5389) && (att_length < att_length_pad))
1884
26
                proto_tree_add_uint(att_tree, hf_stun_att_padding, tvb, offset+att_length, att_length_pad-att_length, att_length_pad-att_length);
1885
156
            offset += att_length_pad;
1886
156
        }
1887
22
    }
1888
1889
61
    if (found_turn_attributes) {
1890
        /* At least one STUN/TURN implementation (Facetime) uses unknown/custom
1891
         * TURN methods to setup a Channel Data, so the previous check to set
1892
         * "is_turn" variable fails. Fortunately, standard TURN attributes are still
1893
         * used in the replies */
1894
0
        is_turn = true;
1895
0
    }
1896
1897
    /* We used to set the conversation to the non-heuristic dissector only if
1898
     * there was a TURN related message, but it should be ok to set it from
1899
     * heuristic to non-heuristic if we see any STUN message with a valid
1900
     * message cookie. (We do that in the heuristic wrapper functions.)
1901
     */
1902
1903
61
    if (!PINFO_FD_VISITED(pinfo) && is_turn && (pinfo->ptype == PT_TCP)
1904
0
        && (msg_type_method == CONNECTION_BIND) && (msg_type_class == SUCCESS_RESPONSE)) {
1905
        /* RFC 6062: after the ConnectionBind exchange, the connection is no longer framed as TURN;
1906
           instead, it is an unframed pass-through.
1907
           Starting from next frame set conversation dissector to data */
1908
0
        conversation_set_dissector_from_frame_number(conversation, pinfo->num+1, data_handle);
1909
0
    }
1910
61
    return reported_length;
1911
82
}
1912
1913
static int
1914
dissect_stun_udp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1915
0
{
1916
0
    return dissect_stun_message(tvb, pinfo, tree, true);
1917
0
}
1918
1919
static int
1920
dissect_stun_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1921
34
{
1922
34
    return udp_dissect_pdus(tvb, pinfo, tree, MIN_HDR_LEN, test_stun_udp,
1923
34
        get_stun_message_len, dissect_stun_udp_pdu, data);
1924
34
}
1925
1926
static int
1927
dissect_stun_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1928
291
{
1929
291
    return dissect_stun_message(tvb, pinfo, tree, false);
1930
291
}
1931
1932
static int
1933
dissect_stun_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1934
62
{
1935
62
    tcp_dissect_pdus(tvb, pinfo, tree, true, MIN_HDR_LEN,
1936
62
        get_stun_message_len, dissect_stun_tcp_pdu, data);
1937
62
    return tvb_reported_length(tvb);
1938
62
}
1939
1940
static bool
1941
dissect_stun_heur_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1942
2.88k
{
1943
2.88k
    conversation_t *conversation;
1944
2.88k
    unsigned captured_length;
1945
2.88k
    unsigned tcp_framing_offset;
1946
1947
    /* There might be multiple STUN messages in a TCP payload: try finding a valid
1948
       message and then switch to non-heuristic TCP dissector which will handle
1949
       multiple messages and reassembler stuff correctly */
1950
1951
2.88k
    captured_length = tvb_captured_length(tvb);
1952
2.88k
    if (captured_length < MIN_HDR_LEN)
1953
124
        return false;
1954
1955
2.76k
    tcp_framing_offset = 0;
1956
2.76k
    if ((captured_length >= TCP_FRAME_COOKIE_LEN) &&
1957
2.57k
        (tvb_get_ntohl(tvb, 6) == MESSAGE_COOKIE)) {
1958
        /*
1959
         * The magic cookie is off by two, so this appears to be
1960
         * RFC 4571 framing, as per RFC 6544; the STUN/TURN
1961
         * ChannelData header begins after the 2-octet
1962
         * RFC 4571 length field.
1963
         */
1964
1
        tcp_framing_offset = 2;
1965
1
    }
1966
1967
2.76k
    if (!test_stun(pinfo, tvb, tcp_framing_offset, true, false)) {
1968
2.74k
        return false;
1969
2.74k
    }
1970
1971
    /*
1972
     * When in heuristic dissector mode, if this is a STUN message, set
1973
     * the 5-tuple conversation to always decode as non-heuristic. The
1974
     * odds of incorrectly identifying a random packet as a STUN message
1975
     * (other than TURN ChannelData) is small, especially with RFC 7983
1976
     * implemented. A ChannelData message won't be matched when in heuristic
1977
     * mode.
1978
     */
1979
21
    conversation = find_or_create_conversation(pinfo);
1980
21
    conversation_set_dissector(conversation, stun_tcp_handle);
1981
1982
21
    dissect_stun_tcp(tvb, pinfo, tree, data);
1983
21
    return true;
1984
2.76k
}
1985
1986
static bool
1987
dissect_stun_heur_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1988
1.27k
{
1989
1.27k
    conversation_t *conversation;
1990
1991
1.27k
    if (udp_dissect_pdus(tvb, pinfo, tree, MIN_HDR_LEN, test_stun_udp_heur,
1992
1.27k
        get_stun_message_len, dissect_stun_udp_pdu, data) > 0) {
1993
1994
        /*
1995
         * When in heuristic dissector mode, if this is a STUN message, set
1996
         * the 5-tuple conversation to always decode as non-heuristic. The
1997
         * odds of incorrectly identifying a random packet as a STUN message
1998
         * (other than TURN ChannelData) is small, especially with RFC 7983
1999
         * implemented. A ChannelData message won't be matched when in heuristic
2000
         * mode.
2001
         */
2002
0
        conversation = find_or_create_conversation(pinfo);
2003
0
        conversation_set_dissector(conversation, stun_udp_handle);
2004
2005
0
        return true;
2006
0
    }
2007
2008
1.27k
    return false;
2009
1.27k
}
2010
2011
void
2012
proto_register_stun(void)
2013
16
{
2014
16
    static hf_register_info hf[] = {
2015
2016
16
        { &hf_stun_channel,
2017
16
          { "Channel Number", "stun.channel", FT_UINT16,
2018
16
            BASE_HEX, NULL,  0x0, NULL, HFILL }
2019
16
        },
2020
2021
        /* ////////////////////////////////////// */
2022
16
        { &hf_stun_tcp_frame_length,
2023
16
          { "TCP Frame Length", "stun.tcp_frame_length", FT_UINT16,
2024
16
            BASE_DEC, NULL, 0x0, NULL, HFILL }
2025
16
        },
2026
16
        { &hf_stun_type,
2027
16
          { "Message Type", "stun.type", FT_UINT16,
2028
16
            BASE_HEX, NULL,0, NULL, HFILL }
2029
16
        },
2030
16
        { &hf_stun_type_class,
2031
16
          { "Message Class", "stun.type.class", FT_UINT16,
2032
16
            BASE_HEX, NULL, 0x0110, NULL, HFILL }
2033
16
        },
2034
16
        { &hf_stun_type_method,
2035
16
          { "Message Method", "stun.type.method", FT_UINT16,
2036
16
            BASE_HEX, NULL, 0x3EEF, NULL, HFILL }
2037
16
        },
2038
16
        { &hf_stun_type_method_assignment,
2039
16
          { "Message Method Assignment", "stun.type.method-assignment", FT_UINT16,
2040
16
            BASE_HEX, VALS(assignments), 0x2000, NULL, HFILL }
2041
16
        },
2042
16
        { &hf_stun_length,
2043
16
          { "Message Length", "stun.length", FT_UINT16,
2044
16
            BASE_DEC, NULL, 0x0, "Payload (attributes) length", HFILL }
2045
16
        },
2046
16
        { &hf_stun_cookie,
2047
16
          { "Message Cookie", "stun.cookie", FT_BYTES,
2048
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2049
16
        },
2050
16
        { &hf_stun_id,
2051
16
          { "Message Transaction ID", "stun.id", FT_BYTES,
2052
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2053
16
        },
2054
16
        { &hf_stun_attributes,
2055
16
          { "Attributes", "stun.attributes", FT_NONE,
2056
16
            BASE_NONE, NULL,  0x0, NULL, HFILL }
2057
16
        },
2058
16
        { &hf_stun_attr,
2059
16
          { "Attribute Type", "stun.attribute", FT_UINT16,
2060
16
            BASE_HEX, NULL, 0, NULL, HFILL }
2061
16
        },
2062
16
        { &hf_stun_response_in,
2063
16
          { "Response In", "stun.response-in", FT_FRAMENUM,
2064
16
            BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0, "The response to this STUN query is in this frame", HFILL }
2065
16
        },
2066
16
        { &hf_stun_response_to,
2067
16
          { "Request In", "stun.response-to", FT_FRAMENUM,
2068
16
            BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0, "This is a response to the STUN Request in this frame", HFILL }
2069
16
        },
2070
16
        { &hf_stun_time,
2071
16
          { "Time", "stun.time", FT_RELATIVE_TIME,
2072
16
            BASE_NONE, NULL, 0x0, "The time between the Request and the Response", HFILL }
2073
16
        },
2074
16
        { &hf_stun_duplicate,
2075
16
          { "Duplicated original message in", "stun.reqduplicate", FT_FRAMENUM,
2076
16
            BASE_NONE, NULL, 0x0, "This is a duplicate of STUN message in this frame", HFILL }
2077
16
        },
2078
        /* ////////////////////////////////////// */
2079
16
        { &hf_stun_att_type,
2080
16
          { "Attribute Type", "stun.att.type", FT_UINT16,
2081
16
            BASE_HEX, NULL, 0x0, NULL, HFILL }
2082
16
        },
2083
16
        { &hf_stun_att_type_comprehension,
2084
16
          { "Attribute Type Comprehension", "stun.att.type.comprehension", FT_UINT16,
2085
16
            BASE_HEX, VALS(comprehensions), 0x8000, NULL, HFILL }
2086
16
        },
2087
16
        { &hf_stun_att_type_assignment,
2088
16
          { "Attribute Type Assignment", "stun.att.type.assignment", FT_UINT16,
2089
16
            BASE_HEX, VALS(assignments), 0x4000, NULL, HFILL }
2090
16
        },
2091
16
        { &hf_stun_att_length,
2092
16
          { "Attribute Length", "stun.att.length", FT_UINT16,
2093
16
            BASE_DEC, NULL, 0x0, NULL, HFILL }
2094
16
        },
2095
16
        { &hf_stun_att_family,
2096
16
          { "Protocol Family", "stun.att.family", FT_UINT8,
2097
16
            BASE_HEX, VALS(attributes_family), 0x0, NULL, HFILL }
2098
16
        },
2099
16
        { &hf_stun_att_ipv4,
2100
16
          { "IP", "stun.att.ipv4", FT_IPv4,
2101
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2102
16
        },
2103
16
        { &hf_stun_att_ipv6,
2104
16
          { "IP", "stun.att.ipv6", FT_IPv6,
2105
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2106
16
        },
2107
16
        { &hf_stun_att_port,
2108
16
          { "Port", "stun.att.port", FT_UINT16,
2109
16
            BASE_DEC, NULL, 0x0, NULL, HFILL }
2110
16
        },
2111
16
        { &hf_stun_att_username,
2112
16
          { "Username", "stun.att.username", FT_STRING,
2113
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2114
16
        },
2115
16
        { &hf_stun_att_username_opaque,
2116
16
          { "Username", "stun.att.username.opaque", FT_BYTES,
2117
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2118
16
        },
2119
16
        { &hf_stun_att_password,
2120
16
          { "Password", "stun.att.password", FT_BYTES,
2121
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2122
16
        },
2123
16
        { &hf_stun_att_padding,
2124
16
          { "Padding", "stun.att.padding", FT_UINT16,
2125
16
            BASE_DEC, NULL, 0x0, NULL, HFILL }
2126
16
        },
2127
16
        { &hf_stun_att_hmac,
2128
16
          { "HMAC-SHA1", "stun.att.hmac", FT_BYTES,
2129
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2130
16
        },
2131
16
        { &hf_stun_att_crc32,
2132
16
          { "CRC-32", "stun.att.crc32", FT_UINT32,
2133
16
            BASE_HEX, NULL, 0x0, NULL, HFILL }
2134
16
        },
2135
16
        { &hf_stun_att_crc32_status,
2136
16
          { "CRC-32 Status", "stun.att.crc32.status", FT_UINT8,
2137
16
            BASE_NONE, VALS(proto_checksum_vals), 0x0, NULL, HFILL }
2138
16
        },
2139
16
        { &hf_stun_att_error_class,
2140
16
          { "Error Class","stun.att.error.class", FT_UINT8,
2141
16
            BASE_DEC, NULL, 0x07, NULL, HFILL}
2142
16
        },
2143
16
        { &hf_stun_att_error_number,
2144
16
          { "Error Code","stun.att.error", FT_UINT8,
2145
16
            BASE_DEC, NULL, 0x0, NULL, HFILL}
2146
16
        },
2147
16
        { &hf_stun_att_error_reason,
2148
16
          { "Error Reason Phrase","stun.att.error.reason", FT_STRING,
2149
16
            BASE_NONE, NULL, 0x0, NULL, HFILL}
2150
16
        },
2151
16
        { &hf_stun_att_realm,
2152
16
          { "Realm", "stun.att.realm", FT_STRING,
2153
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2154
16
        },
2155
16
        { &hf_stun_att_nonce,
2156
16
          { "Nonce", "stun.att.nonce", FT_STRING,
2157
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2158
16
        },
2159
16
        { &hf_stun_att_unknown,
2160
16
          { "Unknown Attribute","stun.att.unknown", FT_UINT16,
2161
16
            BASE_HEX, NULL, 0x0, NULL, HFILL}
2162
16
        },
2163
16
        { &hf_stun_att_xor_ipv4,
2164
16
          { "IP (XOR-d)", "stun.att.ipv4-xord", FT_BYTES,
2165
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2166
16
        },
2167
16
        { &hf_stun_att_xor_ipv6,
2168
16
          { "IP (XOR-d)", "stun.att.ipv6-xord", FT_BYTES,
2169
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2170
16
        },
2171
16
        { &hf_stun_att_xor_port,
2172
16
          { "Port (XOR-d)", "stun.att.port-xord", FT_BYTES,
2173
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2174
16
        },
2175
16
        { &hf_stun_att_icmp_type,
2176
16
          { "ICMP type", "stun.att.icmp.type", FT_UINT8,
2177
16
            BASE_DEC, NULL, 0x0, NULL, HFILL}
2178
16
         },
2179
16
        { &hf_stun_att_icmp_code,
2180
16
          { "ICMP code", "stun.att.icmp.code", FT_UINT8,
2181
16
            BASE_DEC, NULL, 0x0, NULL, HFILL}
2182
16
         },
2183
16
        { &hf_stun_att_ms_turn_unknown_8006,
2184
16
          { "Unknown8006", "stun.att.unknown8006", FT_BYTES,
2185
16
            BASE_NONE, NULL, 0x0, "MS-TURN Unknown Attribute 0x8006", HFILL }
2186
16
        },
2187
16
        { &hf_stun_att_software,
2188
16
          { "Software","stun.att.software", FT_STRING,
2189
16
            BASE_NONE, NULL, 0x0, NULL, HFILL}
2190
16
        },
2191
16
        { &hf_stun_att_priority,
2192
16
          { "Priority", "stun.att.priority", FT_UINT32,
2193
16
            BASE_DEC, NULL, 0x0, NULL, HFILL}
2194
16
         },
2195
16
        { &hf_stun_att_tie_breaker,
2196
16
          { "Tie breaker", "stun.att.tie-breaker", FT_BYTES,
2197
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2198
16
        },
2199
16
        { &hf_stun_att_lifetime,
2200
16
          { "Lifetime", "stun.att.lifetime", FT_UINT32,
2201
16
            BASE_DEC, NULL, 0x0, "Session idle time remaining (seconds)", HFILL}
2202
16
         },
2203
16
        { &hf_stun_att_change_ip,
2204
16
          { "Change IP","stun.att.change-ip", FT_BOOLEAN,
2205
16
            16, TFS(&tfs_set_notset), 0x0004, NULL, HFILL}
2206
16
        },
2207
16
        { &hf_stun_att_change_port,
2208
16
          { "Change Port","stun.att.change-port", FT_BOOLEAN,
2209
16
            16, TFS(&tfs_set_notset), 0x0002, NULL, HFILL}
2210
16
        },
2211
16
        { &hf_stun_att_pw_alg,
2212
16
          { "Password Algorithm", "stun.att.pw_alg", FT_UINT16,
2213
16
            BASE_DEC, VALS(password_algorithm_vals), 0x0, NULL, HFILL }
2214
16
        },
2215
16
        { &hf_stun_att_pw_alg_param_len,
2216
16
          { "Password Algorithm Length", "stun.att.pw_alg_len", FT_UINT16,
2217
16
            BASE_DEC, NULL, 0x0, NULL, HFILL }
2218
16
        },
2219
16
        { &hf_stun_att_pw_alg_param_data,
2220
16
          { "Password Algorithm Data", "stun.att.pw_alg_data", FT_BYTES,
2221
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2222
16
        },
2223
16
        { &hf_stun_att_reserve_next,
2224
16
          { "Reserve next","stun.att.even-port.reserve-next", FT_UINT8,
2225
16
            BASE_DEC, VALS(attributes_reserve_next), 0x80, NULL, HFILL}
2226
16
        },
2227
16
        { &hf_stun_att_cache_timeout,
2228
16
          { "Cache timeout", "stun.att.cache-timeout", FT_UINT32,
2229
16
            BASE_DEC, NULL, 0x0, NULL, HFILL}
2230
16
         },
2231
16
        { &hf_stun_att_token,
2232
16
          { "Token", "stun.att.token", FT_BYTES,
2233
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2234
16
        },
2235
16
        { &hf_stun_att_value,
2236
16
          { "Value", "stun.value", FT_BYTES,
2237
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2238
16
        },
2239
16
        { &hf_stun_att_reserved,
2240
16
          { "Reserved", "stun.att.reserved", FT_BYTES,
2241
16
            BASE_NONE, NULL, 0x0, NULL, HFILL }
2242
16
        },
2243
16
        { &hf_stun_att_transp,
2244
16
          { "Transport", "stun.att.transp", FT_UINT8,
2245
16
            BASE_HEX, VALS(transportnames), 0x0, NULL, HFILL }
2246
16
        },
2247
16
        { &hf_stun_att_channelnum,
2248
16
          { "Channel-Number", "stun.att.channelnum", FT_UINT16,
2249
16
            BASE_HEX, NULL, 0x0, NULL, HFILL }
2250
16
        },
2251
16
        { &hf_stun_att_magic_cookie,
2252
16
          { "Magic Cookie", "stun.att.magic_cookie", FT_UINT32,
2253
16
            BASE_HEX, NULL, 0x0, NULL, HFILL }
2254
16
        },
2255
16
        { &hf_stun_att_bandwidth,
2256
16
          { "Bandwidth", "stun.port.bandwidth", FT_UINT32,
2257
16
            BASE_DEC, NULL, 0x0, "Peak Bandwidth (kBit/s)", HFILL }
2258
16
        },
2259
2260
16
        { &hf_stun_att_ms_version,
2261
16
          { "MS Version", "stun.att.ms.version", FT_UINT32,
2262
16
            BASE_DEC, VALS(ms_version_vals), 0x0, NULL, HFILL}
2263
16
         },
2264
16
        { &hf_stun_att_ms_version_ice,
2265
16
          { "MS ICE Version", "stun.att.ms.version.ice", FT_UINT32,
2266
16
            BASE_DEC|BASE_RANGE_STRING, RVALS(ms_version_ice_rvals),
2267
16
            0x0, NULL, HFILL}
2268
16
         },
2269
16
        { &hf_stun_att_ms_connection_id,
2270
16
          { "Connection ID", "stun.att.ms.connection_id", FT_BYTES,
2271
16
            BASE_NONE, NULL, 0x0, NULL, HFILL}
2272
16
         },
2273
16
        { &hf_stun_att_ms_sequence_number,
2274
16
          { "Sequence Number", "stun.att.ms.sequence_number", FT_UINT32,
2275
16
            BASE_DEC, NULL, 0x0, NULL, HFILL}
2276
16
         },
2277
16
        { &hf_stun_att_ms_stream_type,
2278
16
          { "Stream Type", "stun.att.ms.stream_type", FT_UINT16,
2279
16
            BASE_DEC, VALS(ms_stream_type_vals), 0x0, NULL, HFILL}
2280
16
         },
2281
16
        { &hf_stun_att_ms_service_quality,
2282
16
          { "Service Quality", "stun.att.ms.service_quality", FT_UINT16,
2283
16
            BASE_DEC, VALS(ms_service_quality_vals), 0x0, NULL, HFILL}
2284
16
         },
2285
16
         { &hf_stun_att_ms_foundation,
2286
16
           { "Foundation", "stun.att.ms.foundation", FT_STRING,
2287
16
             BASE_NONE, NULL, 0x0, NULL, HFILL}
2288
16
          },
2289
16
        { &hf_stun_att_ms_multiplexed_turn_session_id,
2290
16
          { "MS Multiplexed TURN Session Id", "stun.att.ms.multiplexed_turn_session_id", FT_UINT64,
2291
16
            BASE_HEX, NULL, 0x0, NULL, HFILL}
2292
16
         },
2293
16
        { &hf_stun_att_ms_turn_session_id,
2294
16
          { "MS TURN Session Id", "stun.att.ms.turn_session_id", FT_UINT64,
2295
16
            BASE_HEX, NULL, 0x0, NULL, HFILL}
2296
16
         },
2297
16
        { &hf_stun_att_bandwidth_acm_type,
2298
16
          { "Message Type", "stun.att.bandwidth_acm.type", FT_UINT16,
2299
16
            BASE_DEC, VALS(bandwidth_acm_type_vals), 0x0, NULL, HFILL}
2300
16
         },
2301
16
        { &hf_stun_att_bandwidth_rsv_id,
2302
16
          { "Reservation ID", "stun.att.bandwidth_rsv_id", FT_BYTES,
2303
16
            BASE_NONE, NULL, 0x0, NULL, HFILL}
2304
16
         },
2305
16
        { &hf_stun_att_bandwidth_rsv_amount_misb,
2306
16
          { "Minimum Send Bandwidth", "stun.att.bandwidth_rsv_amount.misb", FT_UINT32,
2307
16
            BASE_DEC, NULL, 0x0, "In kilobits per second", HFILL}
2308
16
         },
2309
16
        { &hf_stun_att_bandwidth_rsv_amount_masb,
2310
16
          { "Maximum Send Bandwidth", "stun.att.bandwidth_rsv_amount.masb", FT_UINT32,
2311
16
            BASE_DEC, NULL, 0x0, "In kilobits per second", HFILL}
2312
16
         },
2313
16
        { &hf_stun_att_bandwidth_rsv_amount_mirb,
2314
16
          { "Minimum Receive Bandwidth", "stun.att.bandwidth_rsv_amount.mirb", FT_UINT32,
2315
16
            BASE_DEC, NULL, 0x0, "In kilobits per second", HFILL}
2316
16
         },
2317
16
        { &hf_stun_att_bandwidth_rsv_amount_marb,
2318
16
          { "Maximum Receive Bandwidth", "stun.att.bandwidth_rsv_amount.marb", FT_UINT32,
2319
16
            BASE_DEC, NULL, 0x0, "In kilobits per second", HFILL}
2320
16
         },
2321
16
        { &hf_stun_att_address_rp_a,
2322
16
          { "Valid", "stun.att.address_rp.valid", FT_BOOLEAN,
2323
16
            32, TFS(&tfs_yes_no), 0x80000000, NULL, HFILL}
2324
16
         },
2325
16
        { &hf_stun_att_address_rp_b,
2326
16
          { "PSTN", "stun.att.address_rp.pstn", FT_BOOLEAN,
2327
16
            32, TFS(&tfs_yes_no), 0x40000000, NULL, HFILL}
2328
16
         },
2329
16
        { &hf_stun_att_address_rp_rsv1,
2330
16
          { "Reserved", "stun.att.address_rp.reserved", FT_UINT32,
2331
16
            BASE_HEX, NULL, 0x3FFFFFFF, NULL, HFILL}
2332
16
         },
2333
16
        { &hf_stun_att_address_rp_rsv2,
2334
16
          { "Reserved", "stun.att.address_rp.reserved", FT_UINT32,
2335
16
            BASE_HEX, NULL, 0x7FFFFFFF, NULL, HFILL}
2336
16
         },
2337
16
        { &hf_stun_att_address_rp_masb,
2338
16
          { "Maximum Send Bandwidth", "stun.att.address_rp.masb", FT_UINT32,
2339
16
            BASE_DEC, NULL, 0x0, "In kilobits per second", HFILL}
2340
16
         },
2341
16
        { &hf_stun_att_address_rp_marb,
2342
16
          { "Maximum Receive Bandwidth", "stun.att.address_rp.marb", FT_UINT32,
2343
16
            BASE_DEC, NULL, 0x0, "In kilobits per second", HFILL}
2344
16
         },
2345
16
        { &hf_stun_att_sip_dialog_id,
2346
16
          { "SIP Dialog ID", "stun.att.sip_dialog_id", FT_BYTES,
2347
16
            BASE_NONE, NULL, 0x0, NULL, HFILL}
2348
16
         },
2349
16
        { &hf_stun_att_sip_call_id,
2350
16
          { "SIP Call ID", "stun.att.sip_call_id", FT_BYTES,
2351
16
            BASE_NONE, NULL, 0x0, NULL, HFILL}
2352
16
         },
2353
16
        { &hf_stun_att_lp_peer_location,
2354
16
          { "Peer Location", "stun.att.lp.peer_location", FT_UINT8,
2355
16
            BASE_DEC, VALS(location_vals), 0x0, NULL, HFILL}
2356
16
         },
2357
16
        { &hf_stun_att_lp_self_location,
2358
16
          { "Self Location", "stun.att.lp.seft_location", FT_UINT8,
2359
16
            BASE_DEC, VALS(location_vals), 0x0, NULL, HFILL}
2360
16
         },
2361
16
        { &hf_stun_att_lp_federation,
2362
16
          { "Federation", "stun.att.lp.federation", FT_UINT8,
2363
16
            BASE_DEC, VALS(federation_vals), 0x0, NULL, HFILL}
2364
16
         },
2365
16
        { &hf_stun_att_google_network_id,
2366
16
          { "Google Network ID", "stun.att.google.network_id", FT_UINT16,
2367
16
            BASE_DEC, NULL, 0x0, NULL, HFILL}
2368
16
         },
2369
16
        { &hf_stun_att_google_network_cost,
2370
16
          { "Google Network Cost", "stun.att.google.network_cost", FT_UINT16,
2371
16
            BASE_DEC, VALS(google_network_cost_vals), 0x0, NULL, HFILL}
2372
16
         },
2373
16
        { &hf_stun_network_version,
2374
16
          { "STUN Network Version", "stun.network_version", FT_UINT8,
2375
16
            BASE_DEC, VALS(network_versions_vals), 0x0, NULL, HFILL }
2376
16
        },
2377
16
    };
2378
2379
    /* Setup protocol subtree array */
2380
16
    static int *ett[] = {
2381
16
        &ett_stun,
2382
16
        &ett_stun_type,
2383
16
        &ett_stun_att_all,
2384
16
        &ett_stun_att,
2385
16
        &ett_stun_att_type,
2386
16
    };
2387
2388
16
    static ei_register_info ei[] = {
2389
16
        { &ei_stun_short_packet,
2390
16
        { "stun.short_packet", PI_MALFORMED, PI_ERROR, "Packet is too short", EXPFILL }},
2391
2392
16
        { &ei_stun_wrong_msglen,
2393
16
        { "stun.wrong_msglen", PI_MALFORMED, PI_ERROR, "Packet length is not multiple of 4 bytes", EXPFILL }},
2394
2395
16
        { &ei_stun_long_attribute,
2396
16
        { "stun.long_attribute", PI_MALFORMED, PI_WARN, "Attribute has trailing data", EXPFILL }},
2397
2398
16
        { &ei_stun_unknown_attribute,
2399
16
        { "stun.unknown_attribute", PI_UNDECODED, PI_WARN, "Attribute unknown", EXPFILL }},
2400
2401
16
        { &ei_stun_fingerprint_bad,
2402
16
        { "stun.att.crc32.bad", PI_CHECKSUM, PI_WARN, "Bad Fingerprint", EXPFILL }},
2403
16
    };
2404
2405
16
    module_t *stun_module;
2406
16
    expert_module_t* expert_stun;
2407
2408
    /* Register the protocol name and description */
2409
16
    proto_stun = proto_register_protocol("Session Traversal Utilities for NAT", "STUN", "stun");
2410
2411
    /* Required function calls to register the header fields and subtrees used */
2412
16
    proto_register_field_array(proto_stun, hf, array_length(hf));
2413
16
    proto_register_subtree_array(ett, array_length(ett));
2414
2415
    /* heuristic subdissectors (used for the DATA field) */
2416
16
    heur_subdissector_list = register_heur_dissector_list_with_description("stun", "STUN DATA message", proto_stun);
2417
2418
16
    register_dissector("stun-tcp", dissect_stun_tcp, proto_stun);
2419
16
    register_dissector("stun-udp", dissect_stun_udp, proto_stun);
2420
2421
    /* Register preferences */
2422
16
    stun_module = prefs_register_protocol(proto_stun, NULL);
2423
16
    prefs_register_enum_preference(stun_module,
2424
16
        "stunversion", "Stun Version", "Stun Version on the Network",
2425
16
                                       &stun_network_version,
2426
16
                                       stun_network_version_vals,
2427
16
                                       false);
2428
2429
16
    expert_stun = expert_register_protocol(proto_stun);
2430
16
    expert_register_field_array(expert_stun, ei, array_length(ei));
2431
16
}
2432
2433
void
2434
proto_reg_handoff_stun(void)
2435
16
{
2436
16
    stun_tcp_handle = find_dissector("stun-tcp");
2437
16
    stun_udp_handle = find_dissector("stun-udp");
2438
2439
16
    dissector_add_uint_with_preference("tcp.port", TCP_PORT_STUN, stun_tcp_handle);
2440
16
    dissector_add_uint_with_preference("udp.port", UDP_PORT_STUN, stun_udp_handle);
2441
2442
    /*
2443
     * SSL/TLS and DTLS Application-Layer Protocol Negotiation (ALPN)
2444
     * protocol ID.
2445
     */
2446
16
    dissector_add_string("tls.alpn", "stun.nat-discovery", stun_tcp_handle);
2447
16
    dissector_add_string("dtls.alpn", "stun.nat-discovery", stun_udp_handle);
2448
2449
16
    heur_dissector_add("udp", dissect_stun_heur_udp, "STUN over UDP", "stun_udp", proto_stun, HEURISTIC_ENABLE);
2450
16
    heur_dissector_add("tcp", dissect_stun_heur_tcp, "STUN over TCP", "stun_tcp", proto_stun, HEURISTIC_ENABLE);
2451
    /* STUN messages may be encapsulated in Send Indication or Channel Data message as DATA payload
2452
     * (in TURN and CLASSICSTUN, both)  */
2453
16
    heur_dissector_add("stun", dissect_stun_heur_udp, "STUN over TURN", "stun_turn", proto_stun, HEURISTIC_DISABLE);
2454
16
    heur_dissector_add("classicstun", dissect_stun_heur_udp, "STUN over CLASSICSTUN", "stun_classicstun", proto_stun, HEURISTIC_DISABLE);
2455
2456
16
    data_handle = find_dissector("data");
2457
16
}
2458
2459
/*
2460
 * Editor modelines
2461
 *
2462
 * Local Variables:
2463
 * c-basic-offset: 4
2464
 * tab-width: 8
2465
 * indent-tabs-mode: nil
2466
 * End:
2467
 *
2468
 * ex: set shiftwidth=4 tabstop=8 expandtab:
2469
 * :indentSize=4:tabSize=8:noTabs=true:
2470
 */