From 80720ebcab8fbaad9acc0eb46d352ed22b8dd0f8 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Fri, 23 Dec 2005 03:43:56 +0000 Subject: from eric wedel kpasswd over tcp support svn path=/trunk/; revision=16885 --- AUTHORS | 6 +- epan/dissectors/packet-kerberos.c | 9 +-- epan/dissectors/packet-kerberos.h | 7 +++ epan/dissectors/packet-kpasswd.c | 113 +++++++++++++++++++++++++++++++++----- 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 { CIGI dissection } +Eric Wedel { + KPASSWD over TCP support +} + + And assorted fixes and enhancements by the people listed above and by: @@ -2457,7 +2462,6 @@ David E. Weekly Steve Ford Masaki Chikama Mohammad Hanif -Eric Wedel Reinhard Speyerer Patrick Kursawe Arsen Chaloyan 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 +#include #include "packet-kerberos.h" #include "packet-ber.h" #include +/* 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); } -- cgit v1.2.3