AMQP: Introduce support for AMQP over TLS/SSL (AMQPS).

Modified dissect_amqp to the new-style dissector.
Added amqp.ssl.port to protocol preferences.
Registered the AMQP dissector with SSL.

Fixed an error in dissect_amqp that appeared when the first segment was smaller
than the minimum header size required to determine the protocol version (8b).

...plus enhanced the AMQP 0-9-1 to display also the protocol id,
so the packets list shows "0-9-1" instead "9-1".

Change-Id: Ia44e0791b6ee78ad594de342c4f2401bad9beb4e
Reviewed-on: https://code.wireshark.org/review/7044
Reviewed-by: Michael Mann <mmann78@netscape.net>
Reviewed-by: Petr Gotthard <petr.gotthard@centrum.cz>
Tested-by: Peter Wu <peter@lekensteyn.nl>
Reviewed-by: Peter Wu <peter@lekensteyn.nl>
This commit is contained in:
Petr Gotthard 2015-02-09 17:18:15 +01:00 committed by Peter Wu
parent 5c2810eb21
commit 4e32899f6c
1 changed files with 44 additions and 32 deletions

View File

@ -44,6 +44,7 @@
#include <epan/expert.h> #include <epan/expert.h>
#include <epan/prefs.h> #include <epan/prefs.h>
#include "packet-tcp.h" #include "packet-tcp.h"
#include "packet-ssl.h"
void proto_register_amqp(void); void proto_register_amqp(void);
@ -51,6 +52,7 @@ void proto_reg_handoff_amqp(void);
/* Generic data */ /* Generic data */
static guint amqp_port = 5672; static guint amqp_port = 5672;
static guint amqps_port = 5671; /* AMQP over TLS/SSL */
/* Generic defines */ /* Generic defines */
@ -405,8 +407,8 @@ typedef struct {
/* Private functions */ /* Private functions */
static void static int
dissect_amqp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); dissect_amqp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data);
static void static void
check_amqp_version(tvbuff_t *tvb, amqp_conv *conn); check_amqp_version(tvbuff_t *tvb, amqp_conv *conn);
@ -2827,22 +2829,20 @@ static struct amqp_defined_types_t amqp_1_0_defined_types[] = {
/* Main dissection routine */ /* Main dissection routine */
static void static int
dissect_amqp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) dissect_amqp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{ {
conversation_t *conv; conversation_t *conv;
amqp_conv *conn; amqp_conv *conn;
guint fixed_length;
guint (*length_getter)(packet_info *, tvbuff_t *, int, void*);
new_dissector_t dissector;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "AMQP"); col_set_str(pinfo->cinfo, COL_PROTOCOL, "AMQP");
col_clear(pinfo->cinfo, COL_INFO); col_clear(pinfo->cinfo, COL_INFO);
/* Minimal frame size is 8 bytes - smaller frames are malformed */ /* We need at least 8 bytes to check the protocol and get the frame size */
if (tvb_reported_length (tvb) < 8) { if (tvb_reported_length (tvb) < 8) {
expert_add_info_format(pinfo, NULL, &ei_amqp_bad_length, "Require frame at least 8 bytes long"); /* But at this moment we don't know how much we will need */
return; pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
return -1; /* need more data */
} }
/* Find (or build) conversation to remember the protocol version */ /* Find (or build) conversation to remember the protocol version */
@ -2855,27 +2855,24 @@ dissect_amqp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
check_amqp_version(tvb, conn); check_amqp_version(tvb, conn);
switch(conn->version) { switch(conn->version) {
case AMQP_V0_9: case AMQP_V0_9:
length_getter = &get_amqp_0_9_message_len; tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 7, get_amqp_0_9_message_len,
dissector = dissect_amqp_0_9_frame; dissect_amqp_0_9_frame, data);
fixed_length = 7;
break; break;
case AMQP_V0_10: case AMQP_V0_10:
length_getter = &get_amqp_0_10_message_len; tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 8, get_amqp_0_10_message_len,
dissector = dissect_amqp_0_10_frame; dissect_amqp_0_10_frame, data);
fixed_length = 8;
break; break;
case AMQP_V1_0: case AMQP_V1_0:
length_getter = &get_amqp_1_0_message_len; tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 8, get_amqp_1_0_message_len,
dissector = dissect_amqp_1_0_frame; dissect_amqp_1_0_frame, data);
fixed_length = 8;
break; break;
default: default:
col_append_str(pinfo->cinfo, COL_INFO, "AMQP (unknown version)"); col_append_str(pinfo->cinfo, COL_INFO, "AMQP (unknown version)");
col_set_fence(pinfo->cinfo, COL_INFO); col_set_fence(pinfo->cinfo, COL_INFO);
return; break;
} }
tcp_dissect_pdus(tvb, pinfo, tree, TRUE, fixed_length,
length_getter, dissector, NULL); return tvb_captured_length(tvb);
} }
static void static void
@ -7533,15 +7530,16 @@ dissect_amqp_0_9_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
/* Heuristic - protocol initialisation frame starts with 'AMQP' */ /* Heuristic - protocol initialisation frame starts with 'AMQP' */
if (tvb_memeql(tvb, 0, "AMQP", 4) == 0) { if (tvb_memeql(tvb, 0, "AMQP", 4) == 0) {
guint8 proto_major; guint8 proto_id, proto_major, proto_minor;
guint8 proto_minor;
wmem_strbuf_t *strbuf; wmem_strbuf_t *strbuf;
proto_id = tvb_get_guint8(tvb, 5);
proto_major = tvb_get_guint8(tvb, 6); proto_major = tvb_get_guint8(tvb, 6);
proto_minor = tvb_get_guint8(tvb, 7); proto_minor = tvb_get_guint8(tvb, 7);
strbuf = wmem_strbuf_new_label(wmem_packet_scope()); strbuf = wmem_strbuf_new_label(wmem_packet_scope());
wmem_strbuf_append_printf(strbuf, wmem_strbuf_append_printf(strbuf,
"Protocol-Header %u-%u", "Protocol-Header %u-%u-%u",
proto_id,
proto_major, proto_major,
proto_minor); proto_minor);
col_append_str(pinfo->cinfo, COL_INFO, wmem_strbuf_get_str(strbuf)); col_append_str(pinfo->cinfo, COL_INFO, wmem_strbuf_get_str(strbuf));
@ -14001,31 +13999,34 @@ proto_register_amqp(void)
proto_amqp = proto_register_protocol( proto_amqp = proto_register_protocol(
"Advanced Message Queueing Protocol", "AMQP", "amqp"); "Advanced Message Queueing Protocol", "AMQP", "amqp");
new_register_dissector("amqp", dissect_amqp, proto_amqp);
proto_register_field_array(proto_amqp, hf, array_length(hf)); proto_register_field_array(proto_amqp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett)); proto_register_subtree_array(ett, array_length(ett));
expert_amqp = expert_register_protocol(proto_amqp); expert_amqp = expert_register_protocol(proto_amqp);
expert_register_field_array(expert_amqp, ei, array_length(ei)); expert_register_field_array(expert_amqp, ei, array_length(ei));
amqp_module = prefs_register_protocol(proto_amqp, proto_reg_handoff_amqp); amqp_module = prefs_register_protocol(proto_amqp, proto_reg_handoff_amqp);
prefs_register_uint_preference(amqp_module, "tcp.amqp_port", prefs_register_uint_preference(amqp_module, "tcp.port",
"AMQP listening TCP Port", "AMQP listening TCP Port",
"Set the TCP port for AMQP" "Set the TCP port for AMQP"
"(if other than the default of 5672)", "(if other than the default of 5672)",
10, &amqp_port); 10, &amqp_port);
prefs_register_uint_preference(amqp_module, "ssl.port",
"AMQPS listening TCP Port",
"Set the TCP port for AMQP over TLS/SSL"
"(if other than the default of 5671)",
10, &amqps_port);
} }
void void
proto_reg_handoff_amqp(void) proto_reg_handoff_amqp(void)
{ {
static gboolean amqp_prefs_initialized = FALSE;
static dissector_handle_t amqp_tcp_handle; static dissector_handle_t amqp_tcp_handle;
static guint old_amqp_port = 0; static guint old_amqp_port = 0;
static guint old_amqps_port = 0;
/* Register as a heuristic TCP dissector */ amqp_tcp_handle = find_dissector("amqp");
if (amqp_prefs_initialized == FALSE) {
amqp_tcp_handle = create_dissector_handle(dissect_amqp, proto_amqp);
amqp_prefs_initialized = TRUE;
}
/* Register TCP port for dissection */ /* Register TCP port for dissection */
if (old_amqp_port != 0 && old_amqp_port != amqp_port){ if (old_amqp_port != 0 && old_amqp_port != amqp_port){
@ -14033,8 +14034,19 @@ proto_reg_handoff_amqp(void)
} }
if (amqp_port != 0 && old_amqp_port != amqp_port) { if (amqp_port != 0 && old_amqp_port != amqp_port) {
old_amqp_port = amqp_port;
dissector_add_uint("tcp.port", amqp_port, amqp_tcp_handle); dissector_add_uint("tcp.port", amqp_port, amqp_tcp_handle);
} }
/* Register for TLS/SSL payload dissection */
if (old_amqps_port != 0 && old_amqps_port != amqps_port){
ssl_dissector_delete(old_amqps_port, "amqp", TRUE);
}
if (amqps_port != 0 && old_amqps_port != amqps_port) {
old_amqps_port = amqps_port;
ssl_dissector_add(amqps_port, "amqp", TRUE);
}
} }
/* /*