from eric wedel
authorsahlberg <sahlberg@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 23 Dec 2005 03:43:56 +0000 (03:43 +0000)
committersahlberg <sahlberg@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 23 Dec 2005 03:43:56 +0000 (03:43 +0000)
kpasswd over tcp support

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@16885 f5534014-38df-0310-8fa8-9805f1628bb7

AUTHORS
epan/dissectors/packet-kerberos.c
epan/dissectors/packet-kerberos.h
epan/dissectors/packet-kpasswd.c

diff --git a/AUTHORS b/AUTHORS
index dedf3eaa8aa3ad9279d71dc6d6229fa99f467f13..7467aa7b225580fc6131fae9f2146a9a6467042a 100644 (file)
--- 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>
index 84e675a0abf7974bde753fc8cfb1c253c2bdf187..ffc2d75463c1406dfce433a1ee2856a09d1a1c50 100644 (file)
@@ -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;
index 8a359b43aca762037f04b55c6f802775e899370a..ccd4747b3e316a60041df3428b45a5689df77100 100644 (file)
@@ -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
 
index 0adda01eb514218498db22c2cd519ecb8837f6ce..9d8cb5b2a8bf337b4cfd90cae979e91df3639045 100644 (file)
 #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);
 }