diff options
author | Peter Wu <peter@lekensteyn.nl> | 2015-02-06 12:31:46 +0100 |
---|---|---|
committer | Peter Wu <peter@lekensteyn.nl> | 2015-02-06 22:51:57 +0100 |
commit | 29c9c40ee4949ab5e61514bf45321a7114623078 (patch) | |
tree | 99a9d6d5217a7248e964cc1da8606de964f83227 | |
parent | e47000012eb7226feab476c64941e311896f8ff3 (diff) | |
download | wireshark-starttls-fixes.tar.gz |
pgsql,imap: add STARTTLS supportstarttls-fixes
The PGSQL "STARTTLS" protocol is documented at
http://www.postgresql.org/docs/9.4/static/protocol-flow.html
While at it, convert some tvb_length[_remaining] users.
Tested against pgsql-ssl.pcapng,
Tested against imap-ssl.pcapng,
http://wiki.wireshark.org/SampleCaptures#SSL_with_decryption_keys
Change-Id: I1a00a6daa7f03de93339c2c13b07b4cfb8cdbd86
-rw-r--r-- | epan/dissectors/packet-imap.c | 47 | ||||
-rw-r--r-- | epan/dissectors/packet-pgsql.c | 59 |
2 files changed, 86 insertions, 20 deletions
diff --git a/epan/dissectors/packet-imap.c b/epan/dissectors/packet-imap.c index 50545fb8c0..845a20cdf8 100644 --- a/epan/dissectors/packet-imap.c +++ b/epan/dissectors/packet-imap.c @@ -29,6 +29,7 @@ #include <epan/packet.h> #include <epan/strutil.h> #include "packet-ssl.h" +#include "packet-ssl-utils.h" void proto_register_imap(void); void proto_reg_handoff_imap(void); @@ -49,11 +50,16 @@ static gint ett_imap = -1; static gint ett_imap_reqresp = -1; static dissector_handle_t imap_handle; +static dissector_handle_t ssl_handle; #define TCP_PORT_IMAP 143 #define TCP_PORT_SSL_IMAP 993 #define MAX_BUFFER 1024 +typedef struct imap_state { + gboolean ssl_requested; +} imap_state_t; + static void dissect_imap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { @@ -78,11 +84,19 @@ dissect_imap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) guchar *command_token; int iter; int commandlen; + conversation_t *conversation; + imap_state_t *session_state; + + conversation = find_or_create_conversation(pinfo); + session_state = (imap_state_t *)conversation_get_proto_data(conversation, proto_imap); + if (!session_state) { + session_state = wmem_new0(wmem_file_scope(), imap_state_t); + session_state->ssl_requested = FALSE; + conversation_add_proto_data(conversation, proto_imap, session_state); + } - tokenbuf = (guchar *)wmem_alloc(wmem_packet_scope(), MAX_BUFFER); - command_token = (guchar *)wmem_alloc(wmem_packet_scope(), MAX_BUFFER); - memset(tokenbuf, '\0', MAX_BUFFER); - memset(command_token, '\0', MAX_BUFFER); + tokenbuf = (guchar *)wmem_alloc0(wmem_packet_scope(), MAX_BUFFER); + command_token = (guchar *)wmem_alloc0(wmem_packet_scope(), MAX_BUFFER); commandlen = 0; folder_offset = 0; folder_tokenlen = 0; @@ -104,14 +118,14 @@ dissect_imap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", is_request ? "Request" : "Response", format_text(line, linelen)); - if (tree) { + { ti = proto_tree_add_item(tree, proto_imap, tvb, offset, -1, ENC_NA); imap_tree = proto_item_add_subtree(ti, ett_imap); hidden_item = proto_tree_add_boolean(imap_tree, hf_imap_isrequest, tvb, 0, 0, is_request); PROTO_ITEM_SET_HIDDEN(hidden_item); - while(tvb_length_remaining(tvb, offset) > 0) { + while(tvb_reported_length_remaining(tvb, offset) > 0) { /* * Find the end of each line @@ -161,7 +175,7 @@ dissect_imap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) for (iter = 0; iter < tokenlen && iter < MAX_BUFFER-1; iter++) { tokenbuf[iter] = g_ascii_tolower(line[iter]); } - if ( TRUE == is_request && strncmp(tokenbuf,"uid",tokenlen) == 0) { + if (tree && is_request && strncmp(tokenbuf, "uid", tokenlen) == 0) { proto_tree_add_item(reqresp_tree, hf_imap_request_uid, tvb, offset, tokenlen, ENC_ASCII|ENC_NA); /* * UID is a precursor to a command, if following the tag, @@ -209,7 +223,7 @@ dissect_imap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) } } - if (commandlen > 0 && ( + if (tree && commandlen > 0 && ( strncmp(command_token, "select", commandlen) == 0 || strncmp(command_token, "examine", commandlen) == 0 || strncmp(command_token, "create", commandlen) == 0 || @@ -228,7 +242,7 @@ dissect_imap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) proto_tree_add_item(reqresp_tree, hf_imap_request_folder, tvb, folder_offset, folder_tokenlen, ENC_ASCII|ENC_NA); } - if ( is_request && (NULL != folder_line) && strncmp(command_token, "copy", commandlen) == 0) { + if (tree && is_request && (NULL != folder_line) && strncmp(command_token, "copy", commandlen) == 0) { /* * Handle the copy command separately since folder * is the second argument for this command. @@ -241,6 +255,20 @@ dissect_imap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) proto_tree_add_item(reqresp_tree, hf_imap_request_folder, tvb, folder_offset, folder_tokenlen, ENC_ASCII|ENC_NA); } + /* If not yet switched to TLS, check for STARTTLS. */ + if (session_state->ssl_requested) { + if (!is_request && session_state->ssl_requested && + strncmp(tokenbuf, "ok", tokenlen) == 0) { + /* STARTTLS accepted, next reply will be TLS. */ + ssl_starttls_ack(ssl_handle, pinfo, imap_handle); + } + session_state->ssl_requested = FALSE; + } + if (is_request && commandlen > 0 && + strncmp(command_token, "starttls", commandlen) == 0) { + /* If next response is OK, then TLS should be commenced. */ + session_state->ssl_requested = TRUE; + } } /* @@ -332,6 +360,7 @@ proto_reg_handoff_imap(void) { dissector_add_uint("tcp.port", TCP_PORT_IMAP, imap_handle); ssl_dissector_add(TCP_PORT_SSL_IMAP, "imap", TRUE); + ssl_handle = find_dissector("ssl"); } /* * Editor modelines - http://www.wireshark.org/tools/modelines.html diff --git a/epan/dissectors/packet-pgsql.c b/epan/dissectors/packet-pgsql.c index 1ac35b151d..343cd4ca2a 100644 --- a/epan/dissectors/packet-pgsql.c +++ b/epan/dissectors/packet-pgsql.c @@ -27,11 +27,15 @@ #include <epan/packet.h> #include <epan/prefs.h> +#include "packet-ssl-utils.h" #include "packet-tcp.h" void proto_register_pgsql(void); void proto_reg_handoff_pgsql(void); +static dissector_handle_t pgsql_handle; +static dissector_handle_t ssl_handle; + static int proto_pgsql = -1; static int hf_frontend = -1; static int hf_type = -1; @@ -88,6 +92,10 @@ static guint pgsql_port = 5432; static gboolean pgsql_desegment = TRUE; static gboolean first_message = TRUE; +typedef struct pgsql_conn_data { + gboolean ssl_requested; +} pgsql_conn_data_t; + static const value_string fe_messages[] = { { 'p', "Password message" }, { 'Q', "Simple query" }, @@ -158,7 +166,8 @@ static const value_string format_vals[] = { }; static void dissect_pgsql_fe_msg(guchar type, guint length, tvbuff_t *tvb, - gint n, proto_tree *tree) + gint n, proto_tree *tree, + pgsql_conn_data_t *conv_data) { guchar c; gint i, siz; @@ -291,8 +300,8 @@ static void dissect_pgsql_fe_msg(guchar type, guint length, tvbuff_t *tvb, /* SSL request */ case 80877103: - /* There's nothing to parse here, but what do we do if the - SSL negotiation succeeds? */ + /* Next reply will be a single byte. */ + conv_data->ssl_requested = TRUE; break; /* Cancellation request */ @@ -551,6 +560,8 @@ dissect_pgsql_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat { proto_item *ti, *hidden_item; proto_tree *ptree; + conversation_t *conversation; + pgsql_conn_data_t *conn_data; gint n; guchar type; @@ -558,6 +569,14 @@ dissect_pgsql_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat guint length; gboolean fe = (pinfo->match_uint == pinfo->destport); + conversation = find_or_create_conversation(pinfo); + conn_data = (pgsql_conn_data_t *)conversation_get_proto_data(conversation, proto_pgsql); + if (!conn_data) { + conn_data = wmem_new(wmem_file_scope(), pgsql_conn_data_t); + conn_data->ssl_requested = FALSE; + conversation_add_proto_data(conversation, proto_pgsql, conn_data); + } + n = 0; type = tvb_get_guint8(tvb, 0); if (type != '\0') @@ -596,7 +615,7 @@ dissect_pgsql_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat ( first_message ? "" : "/" ), type); first_message = FALSE; - if (tree) { + { ti = proto_tree_add_item(tree, proto_pgsql, tvb, 0, -1, ENC_NA); ptree = proto_item_add_subtree(ti, ett_pgsql); @@ -610,12 +629,12 @@ dissect_pgsql_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat n += 4; if (fe) - dissect_pgsql_fe_msg(type, length, tvb, n, ptree); + dissect_pgsql_fe_msg(type, length, tvb, n, ptree, conn_data); else dissect_pgsql_be_msg(type, length, tvb, n, ptree); } - return tvb_length(tvb); + return tvb_captured_length(tvb); } /* This function is called once per TCP packet. It sets COL_PROTOCOL and @@ -625,21 +644,38 @@ dissect_pgsql_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat static int dissect_pgsql(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { - /* conversation_t *cv; */ + conversation_t *conversation; + pgsql_conn_data_t *conn_data; first_message = TRUE; - /* We don't use conversation data yet, but... */ - /* cv = find_or_create_conversation(pinfo); */ + conversation = find_or_create_conversation(pinfo); + conn_data = (pgsql_conn_data_t *)conversation_get_proto_data(conversation, proto_pgsql); col_set_str(pinfo->cinfo, COL_PROTOCOL, "PGSQL"); col_set_str(pinfo->cinfo, COL_INFO, (pinfo->match_uint == pinfo->destport) ? ">" : "<"); + if (conn_data && conn_data->ssl_requested) { + /* Response to SSLRequest. */ + switch (tvb_get_guint8(tvb, 0)) { + case 'S': /* Willing to perform SSL */ + /* Next packet will start using SSL. */ + ssl_starttls_ack(ssl_handle, pinfo, pgsql_handle); + break; + case 'N': /* Unwilling to perform SSL */ + default: /* ErrorMessage when server does not support SSL. */ + /* TODO: maybe add expert info here? */ + break; + } + conn_data->ssl_requested = FALSE; + return tvb_captured_length(tvb); + } + tcp_dissect_pdus(tvb, pinfo, tree, pgsql_desegment, 5, pgsql_length, dissect_pgsql_msg, data); - return tvb_length(tvb); + return tvb_captured_length(tvb); } void @@ -865,7 +901,6 @@ void proto_reg_handoff_pgsql(void) { static gboolean initialized = FALSE; - static dissector_handle_t pgsql_handle; static guint saved_pgsql_port; if (!initialized) { @@ -877,6 +912,8 @@ proto_reg_handoff_pgsql(void) dissector_add_uint("tcp.port", pgsql_port, pgsql_handle); saved_pgsql_port = pgsql_port; + + ssl_handle = find_dissector("ssl"); } /* |