diff options
author | Ronnie Sahlberg <ronnie_sahlberg@ozemail.com.au> | 2005-12-23 03:43:56 +0000 |
---|---|---|
committer | Ronnie Sahlberg <ronnie_sahlberg@ozemail.com.au> | 2005-12-23 03:43:56 +0000 |
commit | 80720ebcab8fbaad9acc0eb46d352ed22b8dd0f8 (patch) | |
tree | 4ed23f83fb07da4d8d147270455351cda5e76757 /epan/dissectors/packet-kpasswd.c | |
parent | 9b61e75bb65a683cf71c044b25f101d9f87c80b6 (diff) |
from eric wedel
kpasswd over tcp support
svn path=/trunk/; revision=16885
Diffstat (limited to 'epan/dissectors/packet-kpasswd.c')
-rw-r--r-- | epan/dissectors/packet-kpasswd.c | 113 |
1 files changed, 98 insertions, 15 deletions
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); } |