summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2015-02-06 12:31:46 +0100
committerPeter Wu <peter@lekensteyn.nl>2015-02-06 22:51:57 +0100
commit29c9c40ee4949ab5e61514bf45321a7114623078 (patch)
tree99a9d6d5217a7248e964cc1da8606de964f83227
parente47000012eb7226feab476c64941e311896f8ff3 (diff)
downloadwireshark-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.c47
-rw-r--r--epan/dissectors/packet-pgsql.c59
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");
}
/*