Add support for dissecting UDT over DTLS

Includes adding per-conversation data to store whether we are over
DTLS or UDP and registering as a heuristic sub-dissector for DTLS.
Future changes will add more use of the conversation structure.

Also included is a capture of UDT over DTLS in test/captures/udt-dtls.pcapng.gz,
the associated private key for the session in test/keys/udt-dtls.key and a
new test in the decryption suite to check this works.

Change-Id: I76826d3b35768d0b58f5335063884616968e5784
Reviewed-on: https://code.wireshark.org/review/22533
Reviewed-by: Peter Wu <peter@lekensteyn.nl>
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
This commit is contained in:
Simon Graham 2017-07-04 10:38:24 -04:00 committed by Michael Mann
parent 723c76b12c
commit ffb8bbd372
4 changed files with 114 additions and 25 deletions

View File

@ -31,6 +31,13 @@
#include <epan/conversation.h>
#include <epan/expert.h>
/*
* Per-conversation information
*/
typedef struct _udt_conversation {
gboolean is_dtls;
} udt_conversation;
/*
* based on http://tools.ietf.org/html/draft-gg-udt-03
*/
@ -111,10 +118,10 @@ static int
dissect_udt(tvbuff_t *tvb, packet_info* pinfo, proto_tree *parent_tree,
void *data _U_)
{
proto_tree *tree;
proto_item *udt_item;
int is_control, type;
guint i;
proto_tree *tree;
proto_item *udt_item;
int is_control, type;
guint i;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "UDT");
col_clear(pinfo->cinfo, COL_INFO);
@ -312,34 +319,65 @@ dissect_udt(tvbuff_t *tvb, packet_info* pinfo, proto_tree *parent_tree,
}
static gboolean
dissect_udt_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
dissect_udt_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data, gboolean is_dtls)
{
conversation_t *conv;
/* Must have at least 24 captured bytes for heuristic check */
if (tvb_captured_length(tvb) < 24)
return FALSE;
/* detect handshake control packet */
if (tvb_get_ntohl(tvb, 0) != (0x80000000 | UDT_PACKET_TYPE_HANDSHAKE))
return FALSE;
/* must be version 4 */
if ((tvb_get_ntohl(tvb, 16) != 4))
return FALSE;
/* must be datagram or stream */
if ((tvb_get_ntohl(tvb, 20) != UDT_HANDSHAKE_TYPE_DGRAM)
&& (tvb_get_ntohl(tvb, 20) != UDT_HANDSHAKE_TYPE_STREAM))
return FALSE;
udt_conversation *udt_conv;
conv = find_or_create_conversation(pinfo);
conversation_set_dissector(conv, udt_handle);
dissect_udt(tvb, pinfo, tree, data);
udt_conv = (udt_conversation *)conversation_get_proto_data(conv, proto_udt);
if (udt_conv) {
// Already identified conversation as UDT - BUT we might have been called from
// the other dissector.
if (is_dtls != udt_conv->is_dtls)
return FALSE;
dissect_udt(tvb, pinfo, tree, data);
} else {
// Check if this is UDT...
/* Must have at least 24 captured bytes for heuristic check */
if (tvb_captured_length(tvb) < 24)
return FALSE;
/* detect handshake control packet */
if (tvb_get_ntohl(tvb, 0) != (0x80000000 | UDT_PACKET_TYPE_HANDSHAKE))
return FALSE;
/* must be version 4 */
if ((tvb_get_ntohl(tvb, 16) != 4))
return FALSE;
/* must be datagram or stream */
if ((tvb_get_ntohl(tvb, 20) != UDT_HANDSHAKE_TYPE_DGRAM)
&& (tvb_get_ntohl(tvb, 20) != UDT_HANDSHAKE_TYPE_STREAM))
return FALSE;
/* This looks like UDT! */
udt_conv = wmem_new0(wmem_file_scope(), udt_conversation);
udt_conv->is_dtls = is_dtls;
conversation_add_proto_data(conv, proto_udt, udt_conv);
// DTLS should remain the dissector of record for encrypted conversations
if (!is_dtls)
conversation_set_dissector(conv, udt_handle);
dissect_udt(tvb, pinfo, tree, data);
}
return TRUE;
}
static gboolean
dissect_udt_heur_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
return dissect_udt_heur(tvb, pinfo, tree, data, FALSE /* Not DTLS */);
}
static gboolean
dissect_udt_heur_dtls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
return dissect_udt_heur(tvb, pinfo, tree, data, TRUE /* Is DTLS */);
}
void proto_register_udt(void)
{
expert_module_t *expert_udt;
@ -493,13 +531,16 @@ void proto_register_udt(void)
expert_udt = expert_register_protocol(proto_udt);
expert_register_field_array(expert_udt, ei, array_length(ei));
register_dissector("udt", dissect_udt, proto_udt);
}
void proto_reg_handoff_udt(void)
{
udt_handle = create_dissector_handle(dissect_udt, proto_udt);
heur_dissector_add("udp", dissect_udt_heur, "UDT over UDP", "udt_udp", proto_udt, HEURISTIC_ENABLE);
heur_dissector_add("udp", dissect_udt_heur_udp, "UDT over UDP", "udt_udp", proto_udt, HEURISTIC_ENABLE);
heur_dissector_add("dtls", dissect_udt_heur_dtls, "UDT over DTLS", "udt_dtls", proto_udt, HEURISTIC_ENABLE);
dissector_add_for_decode_as_with_preference("udp.port", udt_handle);
}

Binary file not shown.

28
test/keys/udt-dtls.key Normal file
View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDg/jR4vVFNpBta
s1uv4IXhqpePHIIuOoOnb2sK6G8gXdCxKm406JLecNuIqq0eUydH6oawar96vYGM
lLKTfvMnN3RgL3wNG6G+x+zYPjMaS6G+X8SPAG/XtlIxzDFdzliJT4WpKw1nNa7V
sryYTYLZ4aX0hbbETuvXhdZTqCUYX8t2TYyTjeTBybWLyXcWZReGShHPlThn55b0
rtUXkUQoTl3iv330jvJX8MN8haRLwr4+s2jYIGhsINdvMziGo89Eh1FYJXeC4en0
FTEzIx9XA8FiVA8Rf1EEJv6syIvE11GGBCrX0Hu1brg7n6Y0TvkQGcL8tbrFDKlE
W7HlQk9TAgMBAAECggEBALfNk8orRxc5gItJSRbWQilH9saYEJV5ggIv2G+x0M7N
NWb2dc/NS+ZipkXwwLqsTcPHiT7oBgNce1AATh6GsFeSSwUk5Z/DuhAkPY2uyoqp
zLm8fNQiFDxSGrXJzW6H2vZZu6Smoi11wp2bhcyaTdJ3L98huVyH6M1J7fyruZo9
Z8GssyCSujfze7cIc7Py1wEEC0+LzGijkc70HDgsxwj6TXKx/ifXi+5tCCesA3z1
6AIe0zMTcwpXRbdEZGO9fvBxGoK9hwiVJ6/sPmxFXWpBfu6TMLJjLcwwvnoNuWdH
83+PfD+sdE7zo6CUEGDHPvJ/Fyq5lIGjEP0ErruGKPkCgYEA9PyUvC3nHkGN+5t9
JNDaNZWEaiBW7w5yQN5MnQCwK3I8ajE+EDoPl0YDhJW4HFS/iwu8WZeb4pN0WLkT
C2K7Tfb+9G7ebLoQ997l0zEcnHqiKA1CqGpu/g0mcVlGFExthvgv9rmt+1QLTXHJ
F/YirWCTyyIgw11iY2ap8u7kSK0CgYEA6xuHHFTtH2pjRXxuOBhwsvA+8oNd/4A8
phNfJgS7t9LYDMqzyer0ixdkae1vH4peZ1USn6326Vx53hYulH0A69iNM7zrNWM7
JI+y0ftyb/Ji7CwpQAd3JVjUjvoQljrpPqrArm8fGhTucqS8E1fY1u98b3N85RrY
u3uAcwGb9/8CgYAys08ovqs1FMYIiz5T7zEpo77ao8S6BphYmmjqmSjcZPDh3T0F
6K4vVVsHBmEq49McOJqLRBgLxQ5wCiVJ1u4CjZpoBcXcZIl8ctHHakOMksiaV1wz
NIux4hDRpnMdYk/MffKXMggymksYhPLkFZlJnlIX2QFEzT++aJHFZ/EwpQKBgCs8
QLiBFao1UlQw8cP3GqKNc8X9Sof1+TFBVroTHMJNT9XqYO28+4OopZqlQ041j+7I
wkgDIekATJj+00oTQtwcUrs0/rwup22tz2C2MPFNTcvIwz03Ij4H++7fJbW617Hi
jNSHMt0FBGSozr1v5jyAhg2o20r2iOzRZWnA3gHZAoGAXkvhtQxD5sdypzUhs6uS
d3PgKTbQK8PLU5KGl7DZ2oaemQ2QUQw0J9tlEQRItTxB+MDf21FddD8n6c1a3zJa
gay7xiarE8JN0pHoQ1qCqZBwWXQRSPiNu8Bxu2oPpUi2iQdBVQG1bACQOToVUDpv
wCW2aisjPbg71ZkZEvhk2cg=
-----END PRIVATE KEY-----

View File

@ -176,6 +176,25 @@ decryption_step_dtls_psk_aes128ccm8() {
test_step_ok
}
# UDT over DTLS 1.2 with RSA key
decryption_step_udt_dtls() {
TEST_KEYS_FILE="$TESTS_DIR/keys/udt-dtls.key"
if [ "$WS_SYSTEM" == "Windows" ] ; then
TEST_KEYS_FILE="`cygpath -w $TEST_KEYS_FILE`"
fi
$TESTS_DIR/run_and_catch_crashes env $TS_DC_ENV $TSHARK $TS_DC_ARGS \
-o dtls.keys_list:"0.0.0.0,0,data,$TEST_KEYS_FILE" \
-Y "dtls && udt.type==ack" \
-r "$CAPTURE_DIR/udt-dtls.pcapng.gz" \
| grep UDT > /dev/null
RETURNVALUE=$?
if [ ! $RETURNVALUE -eq $EXIT_OK ]; then
test_step_failed "Failed to decrypt UDT/DTLS using the server's RSA private key"
return
fi
test_step_ok
}
# IPsec ESP
# https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=12671
decryption_step_ipsec_esp() {
@ -633,6 +652,7 @@ tshark_decryption_suite() {
test_step_add "IEEE 802.11 WPA TDLS Decryption" decryption_step_80211_wpa_tdls
test_step_add "DTLS Decryption" decryption_step_dtls
test_step_add "DTLS 1.2 Decryption (PSK AES-128-CCM-8)" decryption_step_dtls_psk_aes128ccm8
test_step_add "UDT over DTLS 1.2 Decryption" decryption_step_udt_dtls
test_step_add "IPsec ESP Decryption" decryption_step_ipsec_esp
test_step_add "SSL Decryption (private key)" decryption_step_ssl
test_step_add "SSL Decryption (RSA private key with p smaller than q)" decryption_step_ssl_rsa_pq