aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS6
-rw-r--r--epan/dissectors/packet-kerberos.c9
-rw-r--r--epan/dissectors/packet-kerberos.h7
-rw-r--r--epan/dissectors/packet-kpasswd.c113
4 files changed, 113 insertions, 22 deletions
diff --git a/AUTHORS b/AUTHORS
index dedf3eaa8a..7467aa7b22 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -2433,6 +2433,11 @@ Kyle J. Harms <kyle.j.harms [AT] boeing.com> {
CIGI dissection
}
+Eric Wedel <ewedel [AT] bluearc.com> {
+ KPASSWD over TCP support
+}
+
+
And assorted fixes and enhancements by the people listed above
and by:
@@ -2457,7 +2462,6 @@ David E. Weekly <david [AT] weekly.org>
Steve Ford <sford [AT] geeky-boy.com>
Masaki Chikama <masaki-c [AT] is.aist-nara.ac.jp>
Mohammad Hanif <mhanif [AT] nexthop.com>
-Eric Wedel <ewedel [AT] bluearc.com>
Reinhard Speyerer <rspmn [AT] arcor.de>
Patrick Kursawe <phosphan [AT] gentoo.org>
Arsen Chaloyan <achaloyan [AT] yahoo.com>
diff --git a/epan/dissectors/packet-kerberos.c b/epan/dissectors/packet-kerberos.c
index 84e675a0ab..ffc2d75463 100644
--- a/epan/dissectors/packet-kerberos.c
+++ b/epan/dissectors/packet-kerberos.c
@@ -3752,11 +3752,8 @@ static gint dissect_kerberos_common(tvbuff_t *tvb, packet_info *pinfo,
gboolean do_col_protocol,
gboolean have_rm,
kerberos_callbacks *cb);
-static gint kerberos_rm_to_reclen(guint krb_rm);
static void dissect_kerberos_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree);
-static guint get_krb_pdu_len(tvbuff_t *tvb, int offset);
-
gint
@@ -3793,13 +3790,13 @@ dissect_kerberos_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
return dissect_kerberos_common(tvb, pinfo, tree, TRUE, TRUE, FALSE, NULL);
}
-static gint
+gint
kerberos_rm_to_reclen(guint krb_rm)
{
return (krb_rm & KRB_RM_RECLEN);
}
-static guint
+guint
get_krb_pdu_len(tvbuff_t *tvb, int offset)
{
guint krb_rm;
@@ -3840,7 +3837,7 @@ dissect_kerberos_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
/*
* Display the TCP record mark.
*/
-static void
+void
show_krb_recordmark(proto_tree *tree, tvbuff_t *tvb, gint start, guint32 krb_rm)
{
gint rec_len;
diff --git a/epan/dissectors/packet-kerberos.h b/epan/dissectors/packet-kerberos.h
index 8a359b43ac..ccd4747b3e 100644
--- a/epan/dissectors/packet-kerberos.h
+++ b/epan/dissectors/packet-kerberos.h
@@ -54,6 +54,13 @@ int dissect_krb5_cname(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int
int dissect_krb5_realm(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
guint32 kerberos_output_keytype(void);
+guint get_krb_pdu_len(tvbuff_t *tvb, int offset);
+
+gint kerberos_rm_to_reclen(guint krb_rm);
+
+void
+show_krb_recordmark(proto_tree *tree, tvbuff_t *tvb, gint start, guint32 krb_rm);
+
#ifdef HAVE_KERBEROS
#define KRB_MAX_ORIG_LEN 256
diff --git a/epan/dissectors/packet-kpasswd.c b/epan/dissectors/packet-kpasswd.c
index 0adda01eb5..9d8cb5b2a8 100644
--- a/epan/dissectors/packet-kpasswd.c
+++ b/epan/dissectors/packet-kpasswd.c
@@ -30,10 +30,14 @@
#endif
#include <epan/packet.h>
+#include <epan/dissectors/packet-tcp.h>
#include "packet-kerberos.h"
#include "packet-ber.h"
#include <epan/prefs.h>
+/* Desegment Kerberos over TCP messages */
+static gboolean kpasswd_desegment = TRUE;
+
static int proto_kpasswd = -1;
static int hf_kpasswd_message_len = -1;
static int hf_kpasswd_version = -1;
@@ -52,6 +56,7 @@ static gint ett_ChangePasswdData = -1;
#define UDP_PORT_KPASSWD 464
+#define TCP_PORT_KPASSWD 464
static const value_string vers_vals[] = {
@@ -61,6 +66,7 @@ static const value_string vers_vals[] = {
};
+/** Dissects AP-REQ or AP-REP part of password change. */
static void
dissect_kpasswd_ap_req_data(packet_info *pinfo _U_, tvbuff_t *tvb, proto_tree *parent_tree)
{
@@ -157,51 +163,78 @@ static kerberos_callbacks cb_rep[] = {
{ 0, NULL }
};
-static void
+static gint
dissect_kpasswd_krb_priv_message(packet_info *pinfo _U_, tvbuff_t *tvb, proto_tree *parent_tree, gboolean isrequest)
{
proto_item *it;
proto_tree *tree=NULL;
+ gint offset;
if(parent_tree){
it=proto_tree_add_item(parent_tree, hf_kpasswd_krb_priv_message, tvb, 0, -1, FALSE);
tree=proto_item_add_subtree(it, ett_krb_priv_message);
}
if(isrequest){
- dissect_kerberos_main(tvb, pinfo, tree, FALSE, cb_req);
+ offset = dissect_kerberos_main(tvb, pinfo, tree, FALSE, cb_req);
} else {
- dissect_kerberos_main(tvb, pinfo, tree, FALSE, cb_rep);
+ offset = dissect_kerberos_main(tvb, pinfo, tree, FALSE, cb_rep);
}
+
+ /* offset is bytes consumed in child tvb given to us */
+ return offset;
}
-static void
-dissect_kpasswd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static gint
+dissect_kpasswd_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean have_rm)
{
- proto_item *kpasswd_item;
+ proto_item *kpasswd_item=NULL;
proto_tree *kpasswd_tree=NULL;
int offset = 0;
guint16 message_len, version, ap_req_len;
tvbuff_t *next_tvb;
+ /* TCP record mark and length */
+ guint32 krb_rm = 0;
+ gint krb_reclen = 0;
+ gint krb_rm_size = 0; /* bytes consumed by record mark: 0 or 4 */
+
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "KPASSWD");
if (check_col(pinfo->cinfo, COL_INFO))
col_clear(pinfo->cinfo, COL_INFO);
+ /* can't pass have_rm to dissect_kerberos_main, so strip rm first */
+ if (have_rm) {
+ krb_rm = tvb_get_ntohl(tvb, offset);
+ krb_reclen = kerberos_rm_to_reclen(krb_rm);
+ krb_rm_size = 4;
+ /*
+ * What is a reasonable size limit?
+ */
+ if (krb_reclen > 10 * 1024 * 1024) {
+ return (-1);
+ }
+ offset += krb_rm_size;
+ }
+
/* it might be a KERBEROS ERROR */
if(tvb_get_guint8(tvb, offset)==0x7e){
+ /* TCP record mark, if any, not displayed. But hopefully
+ KRB-ERROR dissection will proceed correctly. */
next_tvb=tvb_new_subset(tvb, offset, -1, -1);
- dissect_kerberos_main(next_tvb, pinfo, tree, FALSE, NULL);
- return;
+ return dissect_kerberos_main(next_tvb, pinfo, tree, FALSE, NULL);
}
message_len=tvb_get_ntohs(tvb, offset);
version=tvb_get_ntohs(tvb, offset+2);
ap_req_len=tvb_get_ntohs(tvb, offset+4);
if(tree){
- kpasswd_item=proto_tree_add_item(tree, proto_kpasswd, tvb, offset, message_len, FALSE);
+ kpasswd_item=proto_tree_add_item(tree, proto_kpasswd, tvb, offset-krb_rm_size, message_len+krb_rm_size, FALSE);
kpasswd_tree=proto_item_add_subtree(kpasswd_item, ett_kpasswd);
+ if (have_rm) {
+ show_krb_recordmark(kpasswd_tree, tvb, offset-krb_rm_size, krb_rm);
+ }
}
proto_tree_add_uint(kpasswd_tree, hf_kpasswd_message_len, tvb, offset, 2, message_len);
@@ -211,17 +244,54 @@ dissect_kpasswd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_tree_add_uint(kpasswd_tree, hf_kpasswd_ap_req_len, tvb, offset+4, 2, ap_req_len);
offset+=6;
- /* AP_REQ data */
+ /* AP-REQ / AP-REP data */
next_tvb=tvb_new_subset(tvb, offset, ap_req_len, ap_req_len);
dissect_kpasswd_ap_req_data(pinfo, next_tvb, kpasswd_tree);
offset+=ap_req_len;
- /* KRB-PRIB message */
+ /* KRB-PRIV message */
next_tvb=tvb_new_subset(tvb, offset, -1, -1);
- dissect_kpasswd_krb_priv_message(pinfo, next_tvb, kpasswd_tree, (version==0xff80));
+ offset += dissect_kpasswd_krb_priv_message(pinfo, next_tvb, kpasswd_tree, (version==0xff80));
+
+ proto_item_set_len(kpasswd_item, offset);
+ return offset;
+
+}
+
+static void
+dissect_kpasswd_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+ dissect_kpasswd_common(tvb, pinfo, tree, FALSE);
}
+static void
+dissect_kpasswd_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ pinfo->fragmented = TRUE;
+ if (dissect_kpasswd_common(tvb, pinfo, tree, TRUE) < 0) {
+ /*
+ * The dissector failed to recognize this as a valid
+ * Kerberos message. Mark it as a continuation packet.
+ */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
+ }
+ }
+}
+
+static void
+dissect_kpasswd_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "KPASSWD");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ tcp_dissect_pdus(tvb, pinfo, tree, kpasswd_desegment, 4, get_krb_pdu_len,
+ dissect_kpasswd_tcp_pdu);
+}
void
proto_register_kpasswd(void)
@@ -262,18 +332,31 @@ proto_register_kpasswd(void)
&ett_krb_priv_message,
&ett_ChangePasswdData,
};
+ module_t *kpasswd_module;
proto_kpasswd = proto_register_protocol("MS Kpasswd",
"Kpasswd", "kpasswd");
proto_register_field_array(proto_kpasswd, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register preferences */
+ kpasswd_module = prefs_register_protocol(proto_kpasswd, NULL);
+ prefs_register_bool_preference(kpasswd_module, "desegment",
+ "Reassemble Kpasswd over TCP messages spanning multiple TCP segments",
+ "Whether the Kpasswd dissector should reassemble messages spanning multiple TCP segments."
+ " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
+ &kpasswd_desegment);
}
void
proto_reg_handoff_kpasswd(void)
{
- dissector_handle_t kpasswd_handle;
+ dissector_handle_t kpasswd_handle_udp;
+ dissector_handle_t kpasswd_handle_tcp;
+
+ kpasswd_handle_udp = create_dissector_handle(dissect_kpasswd_udp, proto_kpasswd);
+ kpasswd_handle_tcp = create_dissector_handle(dissect_kpasswd_tcp, proto_kpasswd);
+ dissector_add("udp.port", UDP_PORT_KPASSWD, kpasswd_handle_udp);
+ dissector_add("tcp.port", TCP_PORT_KPASSWD, kpasswd_handle_tcp);
- kpasswd_handle = create_dissector_handle(dissect_kpasswd, proto_kpasswd);
- dissector_add("udp.port", UDP_PORT_KPASSWD, kpasswd_handle);
}