From Tony Schene: Kerberos-over-TCP support.

svn path=/trunk/; revision=7564
This commit is contained in:
Guy Harris 2003-04-25 21:29:19 +00:00
parent 0c743e4338
commit 0e48f176af
3 changed files with 169 additions and 28 deletions

View File

@ -1680,6 +1680,7 @@ Duncan Laurie <duncan [AT] sun.com> {
Tony Schene <Schene_Tony [AT] emc.com> {
Initial stub Kerberos kadmin support
Kerberos-over-TCP support
}
And assorted fixes and enhancements by the people listed above and by:

View File

@ -10,7 +10,7 @@
*
* http://www.isi.edu/people/bcn/krb-revisions/
*
* $Id: packet-kerberos.c,v 1.36 2002/09/10 08:55:34 guy Exp $
* $Id: packet-kerberos.c,v 1.37 2003/04/25 21:29:19 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -48,11 +48,18 @@
#include "asn1.h"
#include "packet-netbios.h"
#include "packet-gssapi.h"
#include "packet-tcp.h"
#include "prefs.h"
#define UDP_PORT_KERBEROS 88
#define TCP_PORT_KERBEROS 88
/* Desegment Kerberos over TCP messages */
static gboolean krb_desegment = TRUE;
static gint proto_kerberos = -1;
static gint hf_krb_rm_reserved = -1;
static gint hf_krb_rm_reclen = -1;
static gint ett_kerberos = -1;
static gint ett_preauth = -1;
@ -63,6 +70,11 @@ static gint ett_ticket = -1;
static gint ett_encrypted = -1;
static gint ett_etype = -1;
static gint ett_additional_tickets = -1;
static gint ett_recordmark = -1;
/* TCP Record Mark */
#define KRB_RM_RESERVED 0x80000000L
#define KRB_RM_RECLEN 0x7fffffffL
#define KRB5_MSG_AS_REQ 10 /* AS-REQ type */
#define KRB5_MSG_AS_REP 11 /* AS-REP type */
@ -248,6 +260,7 @@ static gint ett_additional_tickets = -1;
#define KRB5_ET_KRB5KRB_AP_ERR_METHOD 48
#define KRB5_ET_KRB5KRB_AP_ERR_BADSEQ 49
#define KRB5_ET_KRB5KRB_AP_ERR_INAPP_CKSUM 50
#define KRB5_ET_KRB5KRB_ERR_RESPONSE_TOO_BIG 52
#define KRB5_ET_KRB5KRB_ERR_GENERIC 60
#define KRB5_ET_KRB5KRB_ERR_FIELD_TOOLONG 61
@ -299,6 +312,7 @@ static const value_string krb5_error_codes[] = {
{ KRB5_ET_KRB5KRB_AP_ERR_METHOD, "KRB5KRB_AP_ERR_METHOD" },
{ KRB5_ET_KRB5KRB_AP_ERR_BADSEQ, "KRB5KRB_AP_ERR_BADSEQ" },
{ KRB5_ET_KRB5KRB_AP_ERR_INAPP_CKSUM, "KRB5KRB_AP_ERR_INAPP_CKSUM" },
{ KRB5_ET_KRB5KRB_ERR_RESPONSE_TOO_BIG, "KRB5KRB_ERR_RESPONSE_TOO_BIG"},
{ KRB5_ET_KRB5KRB_ERR_GENERIC, "KRB5KRB_ERR_GENERIC" },
{ KRB5_ET_KRB5KRB_ERR_FIELD_TOOLONG, "KRB5KRB_ERR_FIELD_TOOLONG" },
{ 0, NULL }
@ -384,6 +398,8 @@ static const value_string krb5_msg_types[] = {
{ 0, NULL },
};
static struct { char *set; char *unset; } bitval = { "Set", "Not set" };
static int dissect_PrincipalName(char *title, ASN1_SCK *asn1p,
packet_info *pinfo, proto_tree *tree,
int start_offset);
@ -394,6 +410,19 @@ static int dissect_EncryptedData(char *title, ASN1_SCK *asn1p,
int start_offset);
static int dissect_Addresses(ASN1_SCK *asn1p, packet_info *pinfo,
proto_tree *tree, int start_offset);
static void dissect_kerberos_udp(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree);
static void dissect_kerberos_tcp(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree);
static gint dissect_kerberos_common(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, int do_col_info,
gboolean have_rm);
static void show_krb_recordmark(proto_tree *kerberos_tree, tvbuff_t *tvb,
gint start, guint32 krb_rm);
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);
static const char *
to_error_str(int ret) {
@ -581,8 +610,87 @@ dissect_type_value_pair(ASN1_SCK *asn1p, int *inoff,
*inoff = offset + *val_len;
}
gboolean
gint
dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int do_col_info)
{
return (dissect_kerberos_common(tvb, pinfo, tree, do_col_info, FALSE));
}
static void
dissect_kerberos_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
(void)dissect_kerberos_common(tvb, pinfo, tree, TRUE, FALSE);
}
static gint
kerberos_rm_to_reclen(guint krb_rm)
{
return (krb_rm & KRB_RM_RECLEN);
}
static guint
get_krb_pdu_len(tvbuff_t *tvb, int offset)
{
guint krb_rm;
gint pdulen;
krb_rm = tvb_get_ntohl(tvb, offset);
pdulen = kerberos_rm_to_reclen(krb_rm);
return (pdulen + 4);
}
static void
dissect_kerberos_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
pinfo->fragmented = TRUE;
if (dissect_kerberos_common(tvb, pinfo, tree, TRUE, 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_kerberos_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
tcp_dissect_pdus(tvb, pinfo, tree, krb_desegment, 4, get_krb_pdu_len,
dissect_kerberos_tcp_pdu);
}
/*
* Display the TCP record mark.
*/
static void
show_krb_recordmark(proto_tree *tree, tvbuff_t *tvb, gint start, guint32 krb_rm)
{
gint rec_len;
proto_item *rm_item;
proto_tree *rm_tree;
if (tree == NULL)
return;
rec_len = kerberos_rm_to_reclen(krb_rm);
rm_item = proto_tree_add_text(tree, tvb, start, 4,
"Record Mark: %u %s", rec_len, plurality(rec_len, "byte", "bytes"));
rm_tree = proto_item_add_subtree(rm_item, ett_recordmark);
proto_tree_add_boolean(rm_tree, hf_krb_rm_reserved, tvb, start, 4, krb_rm);
proto_tree_add_uint(rm_tree, hf_krb_rm_reclen, tvb, start, 4, krb_rm);
}
static gint
dissect_kerberos_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
int do_col_info, gboolean have_rm)
{
int offset = 0;
proto_tree *kerberos_tree = NULL;
@ -614,16 +722,36 @@ dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int d
guchar *str;
int tmp_pos1, tmp_pos2;
asn1_open(&asn1, tvb, 0);
/* TCP record mark and length */
guint32 krb_rm = 0;
gint krb_reclen = 0;
if (have_rm) {
krb_rm = tvb_get_ntohl(tvb, offset);
krb_reclen = kerberos_rm_to_reclen(krb_rm);
/*
* What is a reasonable size limit?
*/
if (krb_reclen > 10 * 1024 * 1024) {
return (-1);
}
offset += 4;
}
asn1_open(&asn1, tvb, offset);
/* top header */
KRB_HEAD_DECODE_OR_DIE("top");
protocol_message_type = tag;
if (tree) {
item = proto_tree_add_item(tree, proto_kerberos, tvb, offset,
item_len, FALSE);
item = proto_tree_add_item(tree, proto_kerberos, tvb, 0, -1, FALSE);
kerberos_tree = proto_item_add_subtree(item, ett_kerberos);
}
/*
* If item_len and krb_reclen disagree, which should we trust? Stick
* with item_len for now.
*/
message_end = asn1p->offset + item_len;
/* second header */
@ -634,6 +762,9 @@ dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int d
KRB_DECODE_UINT32_OR_DIE("version", version);
if (kerberos_tree) {
if (have_rm) {
show_krb_recordmark(kerberos_tree, tvb, 0, krb_rm);
}
proto_tree_add_text(kerberos_tree, tvb, offset, length,
"Version: %d",
version);
@ -666,7 +797,7 @@ dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int d
tag == KRB5_KDC_REP_PADATA)) {
/* pre-authentication supplied */
if (tree) {
if (kerberos_tree) {
item = proto_tree_add_text(kerberos_tree, tvb, offset,
item_len, "Pre-Authentication");
preauth_tree = proto_item_add_subtree(item, ett_preauth);
@ -731,7 +862,7 @@ dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int d
*/
/* request body */
KRB_HEAD_DECODE_OR_DIE("body-sequence");
if (tree) {
if (kerberos_tree) {
item = proto_tree_add_text(kerberos_tree, tvb, offset,
item_len, "Request");
request_tree = proto_item_add_subtree(item, ett_request);
@ -864,7 +995,7 @@ dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int d
}
/* additional-tickets supplied */
if (tree) {
if (kerberos_tree) {
item = proto_tree_add_text(kerberos_tree, tvb, offset,
item_len, "Additional Tickets");
additional_tickets_tree = proto_item_add_subtree(item, ett_additional_tickets);
@ -1106,15 +1237,6 @@ dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int d
return offset;
}
static void
dissect_kerberos(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
dissect_kerberos_main(tvb, pinfo, tree, TRUE);
}
static int
dissect_PrincipalName(char *title, ASN1_SCK *asn1p, packet_info *pinfo,
proto_tree *tree, int start_offset)
@ -1434,11 +1556,17 @@ dissect_Ticket(ASN1_SCK *asn1p, packet_info *pinfo,
void
proto_register_kerberos(void) {
/*
proto_register_kerberos(void)
{
static hf_register_info hf[] = {
{ &hf_krb_rm_reserved, {
"Reserved", "kerberos.rm.reserved", FT_BOOLEAN, 32,
&bitval, KRB_RM_RESERVED, "Record mark reserved bit", HFILL }},
{ &hf_krb_rm_reclen, {
"Record Length", "kerberos.rm.length", FT_UINT32, BASE_DEC,
NULL, KRB_RM_RECLEN, "Record length", HFILL }},
};
*/
static gint *ett[] = {
&ett_kerberos,
&ett_preauth,
@ -1449,22 +1577,34 @@ proto_register_kerberos(void) {
&ett_addresses,
&ett_etype,
&ett_additional_tickets,
&ett_recordmark,
};
module_t *krb_module;
proto_kerberos = proto_register_protocol("Kerberos", "KRB5", "kerberos");
/*
proto_register_field_array(proto_kerberos, hf, array_length(hf));
*/
proto_register_subtree_array(ett, array_length(ett));
/* Register preferences */
krb_module = prefs_register_protocol(proto_kerberos, NULL);
prefs_register_bool_preference(krb_module, "desegment",
"Desegment Kerberos over TCP messages",
"Whether the dissector should desegment "
"multi-segment Kerberos messages", &krb_desegment);
}
void
proto_reg_handoff_kerberos(void)
{
dissector_handle_t kerberos_handle;
dissector_handle_t kerberos_handle_udp;
dissector_handle_t kerberos_handle_tcp;
kerberos_handle = create_dissector_handle(dissect_kerberos, proto_kerberos);
dissector_add("udp.port", UDP_PORT_KERBEROS, kerberos_handle);
dissector_add("tcp.port", TCP_PORT_KERBEROS, kerberos_handle);
kerberos_handle_udp = create_dissector_handle(dissect_kerberos_udp,
proto_kerberos);
kerberos_handle_tcp = create_dissector_handle(dissect_kerberos_tcp,
proto_kerberos);
dissector_add("udp.port", UDP_PORT_KERBEROS, kerberos_handle_udp);
dissector_add("tcp.port", TCP_PORT_KERBEROS, kerberos_handle_tcp);
}

View File

@ -1,6 +1,6 @@
/* packet-kerberos.h
*
* $Id: packet-kerberos.h,v 1.6 2002/09/07 08:29:13 jmayer Exp $
* $Id: packet-kerberos.h,v 1.7 2003/04/25 21:29:19 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -26,7 +26,7 @@
/* Function prototypes */
gboolean
gint
dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int do_col_info);
#endif /* __PACKET_KERBEROS_H */