Kerberos 5 dissector, from Wes Hardaker.
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 11 Aug 2000 03:32:53 +0000 (03:32 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 11 Aug 2000 03:32:53 +0000 (03:32 +0000)
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@2250 f5534014-38df-0310-8fa8-9805f1628bb7

AUTHORS
Makefile.am
Makefile.nmake
doc/ethereal.pod.template
packet-kerberos.c [new file with mode: 0644]
packet-kerberos.h [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index 6f9152cdaff17aea9e932095169fb5426df69281..e4a8e77734e8af6e9f3a9449d19302751132f28f 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -371,6 +371,10 @@ Phil Techau <phil_t@altavista.net> {
        BOOTP fixes
 }
 
+Wes Hardaker <wjhardaker@ucdavis.edu> {
+       Kerberos 5 support
+}
+
 Alain Magloire <alainm@rcsm.ece.mcgill.ca> was kind enough to
 give his permission to use his version of snprintf.c.
 
index cbabfb0f5acf7a633649ea3e40ce906272508fc8..6293acfdf15646b18dc0605317acb0baa00d369d 100644 (file)
@@ -1,7 +1,7 @@
 # Makefile.am
 # Automake file for Ethereal
 #
-# $Id: Makefile.am,v 1.218 2000/07/30 07:16:01 guy Exp $
+# $Id: Makefile.am,v 1.219 2000/08/11 03:32:42 guy Exp $
 #
 # Ethereal - Network traffic analyzer
 # By Gerald Combs <gerald@zing.org>
@@ -82,6 +82,7 @@ DISSECTOR_SOURCES = \
        packet-isis-lsp.c \
        packet-isis-snp.c \
        packet-isl.c   \
+       packet-kerberos.c \
        packet-l2tp.c  \
        packet-lapb.c  \
        packet-lapd.c  \
@@ -198,6 +199,7 @@ noinst_HEADERS = \
        packet-isis-lsp.h \
        packet-isis-snp.h \
        packet-isl.h   \
+       packet-kerberos.h \
        packet-lapb.h  \
        packet-lapd.h  \
        packet-ldap.h  \
index cc3cc75165f8f95e80809a42b431ec02c74571ff..b2de00c1feec99b418832c8b63cd3497eefd050c 100644 (file)
@@ -1,7 +1,7 @@
 ## Makefile for building ethereal.exe with Microsoft C and nmake
 ## Use: nmake -f makefile.nmake
 #
-# $Id: Makefile.nmake,v 1.50 2000/07/31 03:45:53 guy Exp $
+# $Id: Makefile.nmake,v 1.51 2000/08/11 03:32:43 guy Exp $
 
 include config.nmake
 
@@ -67,6 +67,7 @@ DISSECTOR_SOURCES = \
        packet-isis-lsp.c \
        packet-isis-snp.c \
        packet-isl.c   \
+       packet-kerberos.c \
        packet-l2tp.c  \
        packet-lapb.c  \
        packet-lapd.c  \
index 4b2b4318ddfdbff21584100bcf6e411b7a348342..b26a65fb0aae00b46c7b8ac2f267250104c1ce40 100644 (file)
@@ -935,6 +935,7 @@ B<http://ethereal.zing.org>.
   David Frascone           <dave@frascone.com>
   Peter Kjellerstedt       <pkj@axis.com>
   Phil Techau              <phil_t@altavista.net>
+  Wes Hardaker             <wjhardaker@ucdavis.edu>
 
 Alain Magloire <alainm@rcsm.ece.mcgill.ca> was kind enough to give his
 permission to use his version of snprintf.c.
diff --git a/packet-kerberos.c b/packet-kerberos.c
new file mode 100644 (file)
index 0000000..a2e95fa
--- /dev/null
@@ -0,0 +1,944 @@
+/* packet-kerberos.c
+ * Routines for Kerberos
+ * Wes Hardaker (c) 2000
+ * wjhardaker@ucdavis.edu
+ *
+ * $Id: packet-kerberos.c,v 1.1 2000/08/11 03:32:43 guy Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Didier Jorand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <glib.h>
+
+#include "packet.h"
+
+#include "asn1.h"
+
+#include "packet-kerberos.h"
+
+#define UDP_PORT_KERBEROS              88
+#define TCP_PORT_KERBEROS              88
+
+static gint ett_kerberos   = -1;
+static gint ett_preauth    = -1;
+static gint ett_addresses  = -1;
+static gint ett_request    = -1;
+static gint ett_princ      = -1;
+static gint ett_ticket     = -1;
+static gint ett_encrypted  = -1;
+static gint ett_etype      = -1;
+static gint proto_kerberos = -1;
+
+#define KRB5_MSG_AS_REQ   0x0a
+#define KRB5_MSG_AS_RESP  0x0b
+#define KRB5_MSG_TGS_REQ  0x0c
+#define KRB5_MSG_TGS_RESP 0x0d
+
+#define KRB5_KDC_REQ_PVNO     0x01
+#define KRB5_KDC_REQ_MSG_TYPE 0x02
+#define KRB5_KDC_REQ_PADATA   0x03
+#define KRB5_KDC_REQ_REQBODY  0x04
+
+#define KRB5_KDC_RESP_PVNO     0x00
+#define KRB5_KDC_RESP_MSG_TYPE 0x01
+#define KRB5_KDC_RESP_PADATA   0x02
+#define KRB5_KDC_RESP_CREALM   0x03
+#define KRB5_KDC_RESP_CNAME    0x04
+#define KRB5_KDC_RESP_TICKET   0x05
+#define KRB5_KDC_RESP_ENC_PART 0x06
+
+#define KRB5_BODY_KDC_OPTIONS            0x00
+#define KRB5_BODY_CNAME                  0x01
+#define KRB5_BODY_REALM                  0x02
+#define KRB5_BODY_SNAME                  0x03
+#define KRB5_BODY_FROM                   0x04
+#define KRB5_BODY_TILL                   0x05
+#define KRB5_BODY_RTIME                  0x06
+#define KRB5_BODY_NONCE                  0x07
+#define KRB5_BODY_ETYPE                  0x08
+#define KRB5_BODY_ADDRESSES              0x09
+#define KRB5_BODY_ENC_AUTHORIZATION_DATA 0x0a
+#define KRB5_BODY_ADDITIONAL_TICKETS     0x0b
+
+#define KRB5_ADDR_IPv4       0x02
+#define KRB5_ADDR_CHAOS      0x05
+#define KRB5_ADDR_XEROX      0x06
+#define KRB5_ADDR_ISO        0x07
+#define KRB5_ADDR_DECNET     0x0c
+#define KRB5_ADDR_APPLETALK  0x10
+
+#define KRB5_ETYPE_NULL                0
+#define KRB5_ETYPE_DES_CBC_CRC         1
+#define KRB5_ETYPE_DES_CBC_MD4         2
+#define KRB5_ETYPE_DES_CBC_MD5         3
+
+#define KRB5_PA_TGS_REQ       0x01
+#define KRB5_PA_ENC_TIMESTAMP 0x02
+#define KRB5_PA_PW_SALT       0x03
+
+static const value_string krb5_preauthentication_types[] = {
+    { KRB5_PA_TGS_REQ      , "PA-TGS-REQ" },
+    { KRB5_PA_ENC_TIMESTAMP, "PA-ENC-TIMESTAMP" },
+    { KRB5_PA_PW_SALT      , "PA-PW-SALT" },
+};
+
+static const value_string krb5_encryption_types[] = {
+    { KRB5_ETYPE_NULL           , "NULL" },
+    { KRB5_ETYPE_DES_CBC_CRC    , "des-cbc-crc" },
+    { KRB5_ETYPE_DES_CBC_MD4    , "des-cbc-md4" },
+    { KRB5_ETYPE_DES_CBC_MD5    , "des-cbc-md5" },
+};
+
+static const value_string krb5_address_types[] = {
+    { KRB5_ADDR_IPv4,  "IPv4"},
+    { KRB5_ADDR_CHAOS, "CHAOS"},
+    { KRB5_ADDR_XEROX, "XEROX"},
+    { KRB5_ADDR_ISO,   "ISO"},
+    { KRB5_ADDR_DECNET,        "DECNET"},
+    { KRB5_ADDR_APPLETALK,     "APPLETALK"}
+};
+
+static const value_string krb5_msg_types[] = {
+       { KRB5_MSG_TGS_REQ,     "TGS-REQ" },
+       { KRB5_MSG_TGS_RESP,    "TGS-RESP" },
+       { KRB5_MSG_AS_REQ,      "AS-REQ" },
+       { KRB5_MSG_AS_RESP,     "AS-RESP" }
+};
+
+const char *
+to_error_str(int ret) {
+    switch (ret) {
+
+        case ASN1_ERR_EMPTY:
+            return("Ran out of data");
+
+        case ASN1_ERR_EOC_MISMATCH:
+            return("EOC mismatch");
+
+        case ASN1_ERR_WRONG_TYPE:
+            return("Wrong type for that item");
+
+        case ASN1_ERR_LENGTH_NOT_DEFINITE:
+            return("Length was indefinite");
+
+        case ASN1_ERR_LENGTH_MISMATCH:
+            return("Length mismatch");
+
+        case ASN1_ERR_WRONG_LENGTH_FOR_TYPE:
+            return("Wrong length for that item's type");
+
+    }
+    return("Unknown error");
+}
+
+void
+krb_proto_tree_add_time(proto_tree *tree, int offset, int str_len,
+                        char *name, guchar *str) {
+    if (tree)
+        proto_tree_add_text(tree, NullTVB, offset, str_len,
+                            "%s: %.4s-%.2s-%.2s %.2s:%.2s:%.2s (%.1s)",
+                            name, str, str+4, str+6,
+                            str+8, str+10, str+12,
+                            str+14);
+}
+
+
+/*
+ * You must be kidding.  I'm going to actually use a macro to do something?
+ *   bad me.  Bad me.
+ */
+
+#define KRB_HEAD_DECODE_OR_DIE(token) \
+   start = asn1p->pointer; \
+   ret = asn1_header_decode (asn1p, &cls, &con, &tag, &def, &item_len); \
+   if (ret != ASN1_ERR_NOERROR && ret != ASN1_ERR_EMPTY) {\
+       col_add_fstr(fd, COL_INFO, "ERROR: Problem at %s: %s", \
+                    token, to_error_str(ret)); \
+       return; \
+   } \
+   if (!def) {\
+       col_add_fstr(fd, COL_INFO, "not definite: %s", token); \
+       fprintf(stderr,"not definite: %s\n", token); \
+       return; \
+   } \
+   offset += (asn1p->pointer - start);
+
+
+#define KRB_DECODE_OR_DIE(token, fn, val) \
+    ret = fn (asn1p, &val, &length); \
+    if (ret != ASN1_ERR_NOERROR) { \
+        col_add_fstr(fd, COL_INFO, "ERROR: Problem at %s: %s", \
+                     token, to_error_str(ret)); \
+        return; \
+    } \
+
+/* dissect_type_value_pair decodes (roughly) this:
+
+    SEQUENCE  {
+                        INTEGER,
+                        OCTET STRING
+    }
+
+    which is all over the place in krb5 */
+
+void
+dissect_type_value_pair(ASN1_SCK *asn1p, int *inoff,
+                        int *type, int *type_len, int *type_off,
+                        guchar **val, int *val_len, int *val_off) {
+    int offset = *inoff;
+    guint cls, con, tag;
+    gboolean def;
+    const guchar *start;
+    guint tmp_len;
+    int ret;
+
+    /* SEQUENCE */
+    start = asn1p->pointer;
+    asn1_header_decode (asn1p, &cls, &con, &tag, &def, &tmp_len);
+    offset += (asn1p->pointer - start);
+
+    /* INT */
+    /* wrapper */
+    start = asn1p->pointer;
+    asn1_header_decode (asn1p, &cls, &con, &tag, &def, &tmp_len);
+    offset += (asn1p->pointer - start);
+
+    if (type_off)
+        *type_off = offset;
+
+    /* value */
+    ret =  asn1_int32_decode(asn1p, type, type_len);
+    if (ret != ASN1_ERR_NOERROR) {
+        fprintf(stderr,"die: type_value_pair: type, %s\n", to_error_str(ret));
+        return;
+    }
+    offset += tmp_len;
+
+    /* OCTET STRING (or generic data) */
+    /* wrapper */
+    start = asn1p->pointer;
+    asn1_header_decode (asn1p, &cls, &con, &tag, &def, val_len);
+    asn1_header_decode (asn1p, &cls, &con, &tag, &def, val_len);
+    offset += asn1p->pointer - start;
+    
+    if (val_off)
+        *val_off = offset;
+
+    /* value */
+    asn1_octet_string_value_decode (asn1p, *val_len, val);
+
+    *inoff = offset + *val_len;
+}
+
+
+void
+dissect_kerberos(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
+{
+    proto_tree *kerberos_tree = NULL;
+    proto_tree *etype_tree = NULL;
+    proto_tree *preauth_tree = NULL;
+    proto_tree *request_tree = NULL;
+    ASN1_SCK asn1, *asn1p = &asn1;
+    proto_item *item = NULL;
+
+    guint length;
+    guint cls, con, tag;
+    gboolean def;
+    guint item_len, total_len;
+    const guchar *start;
+
+    int ret;
+
+    guint protocol_message_type;
+    
+    gint32 version;
+    gint32 msg_type;
+    gint32 preauth_type;
+    gint32 tmp_int;
+
+    /* simple holders */
+    int str_len;
+    guchar *str;
+    int tmp_pos1, tmp_pos2;
+
+    if (check_col(fd, COL_PROTOCOL))
+        col_add_str(fd, COL_PROTOCOL, "KRB5");
+
+    if (tree) {
+        item = proto_tree_add_item(tree, proto_kerberos, NullTVB, offset,
+                                   END_OF_FRAME, FALSE);
+        kerberos_tree = proto_item_add_subtree(item, ett_kerberos);
+    }
+
+    asn1_open(&asn1, &pd[offset], END_OF_FRAME);
+
+    /* top header */
+    KRB_HEAD_DECODE_OR_DIE("top");
+    protocol_message_type = tag;
+    
+    /* second header */
+    KRB_HEAD_DECODE_OR_DIE("top2");
+
+    /* version number */
+    KRB_HEAD_DECODE_OR_DIE("version-wrap");
+    KRB_DECODE_OR_DIE("version", asn1_int32_decode, version);
+
+    if (kerberos_tree) {
+        proto_tree_add_text(kerberos_tree, NullTVB, offset, length,
+                            "Version: %d",
+                            version);
+    }
+    offset += length;
+
+    /* message type */
+    KRB_HEAD_DECODE_OR_DIE("message-type-wrap");
+    KRB_DECODE_OR_DIE("message-type", asn1_int32_decode, msg_type);
+
+    if (kerberos_tree) {
+        proto_tree_add_text(kerberos_tree, NullTVB, offset, length,
+                            "MSG Type: %s",
+                            val_to_str(msg_type, krb5_msg_types,
+                                       "Unknown msg type %#x"));
+    }
+    offset += length;
+
+    if (check_col(fd, COL_INFO))
+        col_add_str(fd, COL_INFO, val_to_str(msg_type, krb5_msg_types,
+                                             "Unknown msg type %#x"));
+
+        /* is preauthentication present? */
+    KRB_HEAD_DECODE_OR_DIE("padata-or-body");
+    if (((protocol_message_type == KRB5_MSG_AS_REQ ||
+          protocol_message_type == KRB5_MSG_TGS_REQ) &&
+         tag == KRB5_KDC_REQ_PADATA) ||
+        ((protocol_message_type == KRB5_MSG_AS_RESP ||
+          protocol_message_type == KRB5_MSG_TGS_RESP) &&
+         tag == KRB5_KDC_RESP_PADATA)) {
+        /* pre-authentication supplied */
+
+        if (tree) {
+            item = proto_tree_add_text(kerberos_tree, NullTVB, offset,
+                                       item_len, "Pre-Authentication");
+            preauth_tree = proto_item_add_subtree(item, ett_preauth);
+        }
+
+        KRB_HEAD_DECODE_OR_DIE("sequence of pa-data");
+        start = asn1p->pointer + item_len;
+
+        while(start > asn1p->pointer) {
+            dissect_type_value_pair(asn1p, &offset,
+                                    &preauth_type, &item_len, &tmp_pos1,
+                                    &str, &str_len, &tmp_pos2);
+
+            if (preauth_tree) {
+                proto_tree_add_text(preauth_tree, NullTVB, tmp_pos1,
+                                    item_len, "Type: %s",
+                                    val_to_str(preauth_type,
+                                               krb5_preauthentication_types,
+                                               "Unknown preauth type %#x"));
+                proto_tree_add_text(preauth_tree, NullTVB, tmp_pos2,
+                                    str_len, "Value: %s",
+                                    bytes_to_str(str, str_len));
+            }
+        }
+        KRB_HEAD_DECODE_OR_DIE("message-body");
+    }
+
+    if (protocol_message_type == KRB5_MSG_AS_REQ ||
+        protocol_message_type == KRB5_MSG_TGS_REQ) {
+    
+        /* request body */
+        KRB_HEAD_DECODE_OR_DIE("body-sequence");
+        if (tree) {
+            item = proto_tree_add_text(kerberos_tree, NullTVB, offset,
+                                       item_len, "Request");
+            request_tree = proto_item_add_subtree(item, ett_request);
+        }
+
+        /* kdc options */
+        KRB_HEAD_DECODE_OR_DIE("kdc options");
+
+        KRB_HEAD_DECODE_OR_DIE("kdc options:bits");
+
+        if (request_tree) {
+                proto_tree_add_text(request_tree, NullTVB, offset, item_len,
+                                    "Options: %s",
+                                    bytes_to_str(asn1.pointer, item_len));
+        }
+        offset += item_len;
+        asn1.pointer += item_len;
+
+        KRB_HEAD_DECODE_OR_DIE("Principal Name");
+
+        if (tag == KRB5_BODY_CNAME) {
+            dissect_PrincipalName("Client Name", asn1p, fd, request_tree,
+                                   &offset);
+            KRB_HEAD_DECODE_OR_DIE("realm name");
+        }
+
+        if (tag == KRB5_BODY_REALM) {
+            dissect_GeneralString(asn1p, &str, &str_len, &item_len);
+            offset += item_len - str_len;
+            if (request_tree) {
+                proto_tree_add_text(request_tree, NullTVB, offset, str_len,
+                                    "Realm: %.*s", str_len, str);
+            }
+            offset += str_len;
+            KRB_HEAD_DECODE_OR_DIE("realm name");
+        } else {
+            return;
+        }
+
+        if (tag == KRB5_BODY_SNAME) {
+            dissect_PrincipalName("Server Name", asn1p, fd, request_tree, &offset);
+            KRB_HEAD_DECODE_OR_DIE("realm name");
+        }
+
+        if (tag == KRB5_BODY_FROM) {
+            dissect_GeneralString(asn1p, &str, &str_len, &item_len);
+            offset += item_len - str_len;
+            krb_proto_tree_add_time(request_tree, offset, str_len,
+                                    "Start Time", str);
+            offset += str_len;
+            KRB_HEAD_DECODE_OR_DIE("realm name");
+        }
+
+        if (tag == KRB5_BODY_TILL) {
+            dissect_GeneralString(asn1p, &str, &str_len, &item_len);
+            offset += item_len - str_len;
+            krb_proto_tree_add_time(request_tree, offset, str_len,
+                                    "End Time", str);
+            offset += str_len;
+            KRB_HEAD_DECODE_OR_DIE("realm name");
+        } else {
+            return;
+        }
+        
+        if (tag == KRB5_BODY_RTIME) {
+            dissect_GeneralString(asn1p, &str, &str_len, &item_len);
+            offset += item_len - str_len;
+            krb_proto_tree_add_time(request_tree, offset, str_len,
+                                    "Renewable Until", str);
+            offset += str_len;
+            KRB_HEAD_DECODE_OR_DIE("realm name");
+        }
+            
+        if (tag == KRB5_BODY_NONCE) {
+            ret =  asn1_int32_decode(asn1p, &tmp_int, &length);
+            if (ret != ASN1_ERR_NOERROR) {
+                fprintf(stderr,"die: nonce, %s\n", to_error_str(ret));
+                return;
+            }
+            if (request_tree) {
+                proto_tree_add_text(request_tree, NullTVB, offset, length,
+                                    "Random Number: %d",
+                                    tmp_int);
+            }
+            offset += length;
+        } else {
+            return;
+        }
+        
+        KRB_HEAD_DECODE_OR_DIE("encryption type spot");
+        if (tag == KRB5_BODY_ETYPE) {
+            KRB_HEAD_DECODE_OR_DIE("encryption type list");
+            if (kerberos_tree) {
+                item = proto_tree_add_text(request_tree, NullTVB, offset,
+                                           item_len, "Encryption Types");
+                etype_tree = proto_item_add_subtree(item, ett_etype);
+            }
+            total_len = item_len;
+            while(total_len > 0) {
+                ret =  asn1_int32_decode(asn1p, &tmp_int, &length);
+                if (ret != ASN1_ERR_NOERROR) {
+                    fprintf(stderr,"die: etype, %s\n", to_error_str(ret));
+                    return;
+                }
+                if (etype_tree) {
+                    proto_tree_add_text(etype_tree, NullTVB, offset, length,
+                                        "Type: %s",
+                                        val_to_str(tmp_int,
+                                                   krb5_encryption_types,
+                                                   "Unknown encryption type %#x"));
+                }
+                offset += length;
+                total_len -= length;
+            }
+        } else {
+            return;
+        }
+
+        KRB_HEAD_DECODE_OR_DIE("addresses");
+        if (tag == KRB5_BODY_ADDRESSES) {
+            /* pre-authentication supplied */
+
+            dissect_Addresses("Addresses", asn1p, fd, kerberos_tree, &offset);
+            KRB_HEAD_DECODE_OR_DIE("auth-data");
+        }
+    } else if (protocol_message_type == KRB5_MSG_AS_RESP ||
+               protocol_message_type == KRB5_MSG_TGS_RESP) {
+        if (tag == KRB5_KDC_RESP_CREALM) {
+            dissect_GeneralString(asn1p, &str, &str_len, &item_len);
+            offset += item_len - str_len;
+            if (kerberos_tree) {
+                proto_tree_add_text(kerberos_tree, NullTVB, offset, str_len,
+                                    "Realm: %.*s", str_len, str);
+            }
+            offset += str_len;
+        } else {
+            return;
+        }
+
+        KRB_HEAD_DECODE_OR_DIE("cname");
+        if (tag == KRB5_KDC_RESP_CNAME) {
+            dissect_PrincipalName("Client Name", asn1p, fd, kerberos_tree,
+                                   &offset);
+        } else {
+            return;
+        }
+        
+        KRB_HEAD_DECODE_OR_DIE("ticket");
+        if (tag == KRB5_KDC_RESP_TICKET) {
+            dissect_ticket("ticket", asn1p, fd, kerberos_tree, &offset);
+        } else {
+            return;
+        }
+
+        KRB_HEAD_DECODE_OR_DIE("enc-msg-part");
+        if (tag == KRB5_KDC_RESP_TICKET) {
+            dissect_EncryptedData("Encrypted Payload", asn1p, fd, kerberos_tree,
+                                  &offset);
+        } else {
+            return;
+        }
+    }
+}
+
+void
+dissect_GeneralString(ASN1_SCK *asn1p, guchar **where,
+                      guint *item_len, guint *pkt_len)
+{
+    guint cls, con, tag;
+    gboolean def;
+    const guchar *start = asn1p->pointer;
+
+    asn1_header_decode (asn1p, &cls, &con, &tag, &def, item_len);
+    asn1_octet_string_value_decode (asn1p, *item_len, where);
+    *pkt_len = asn1p->pointer - start;
+}
+
+void
+dissect_PrincipalName(char *title, ASN1_SCK *asn1p, frame_data *fd,
+                       proto_tree *tree, int *inoff) {
+    proto_tree *princ_tree = NULL;
+    int offset = 0;
+
+    gint32 princ_type;
+
+    const guchar *start;
+    guint cls, con, tag;
+    guint item_len, total_len, type_len;
+    int ret;
+
+    proto_item *item = NULL;
+    guint length;
+    gboolean def;
+
+    int type_offset;
+
+    guchar *name;
+    guint name_len;
+
+    if (inoff)
+        offset = *inoff;
+    
+    /* principal name */
+    KRB_HEAD_DECODE_OR_DIE("principal section");
+
+    KRB_HEAD_DECODE_OR_DIE("principal type");
+    KRB_DECODE_OR_DIE("princ-type", asn1_int32_decode, princ_type);
+    type_offset = offset;
+    type_len = item_len;
+    offset += length;
+
+    KRB_HEAD_DECODE_OR_DIE("cname header");
+    total_len = item_len;
+
+    dissect_GeneralString(asn1p, &name, &name_len, &item_len);
+    offset += item_len - name_len;
+    
+    if (tree) {
+        item = proto_tree_add_text(tree, NullTVB, *inoff, total_len,
+                                   "%s: %.*s", title, (int) name_len, name);
+        princ_tree = proto_item_add_subtree(item, ett_princ);
+
+        proto_tree_add_text(princ_tree, NullTVB, type_offset, type_len,
+                            "Type: %d", princ_type);
+        proto_tree_add_text(princ_tree, NullTVB, offset, name_len,
+                            "Name: %.*s", (int) name_len, name);
+    }
+
+    total_len -= item_len;
+    offset += name_len;
+    
+    while(total_len > 0) {
+        dissect_GeneralString(asn1p, &name, &name_len, &item_len);
+        offset += item_len - name_len;
+        if (princ_tree) {
+            proto_tree_add_text(princ_tree, NullTVB, offset, name_len,
+                                "Name: %.*s", (int) name_len, name);
+        }
+        total_len -= item_len;
+        offset += name_len;
+    }
+    if (inoff)
+        *inoff = offset;
+}
+
+void
+dissect_Addresses(char *title, ASN1_SCK *asn1p, frame_data *fd,
+                  proto_tree *tree, int *inoff) {
+    proto_tree *address_tree = NULL;
+    int offset = 0;
+
+    const guchar *start;
+    guint cls, con, tag;
+    guint item_len;
+    int ret;
+
+    proto_item *item = NULL;
+    gboolean def;
+
+    int tmp_pos1, tmp_pos2;
+    gint32 address_type;
+
+    int str_len;
+    guchar *str;
+
+    if (inoff)
+        offset = *inoff;
+
+    KRB_HEAD_DECODE_OR_DIE("sequence of addresses");
+    if (tree) {
+        item = proto_tree_add_text(tree, NullTVB, offset,
+                                   item_len, "Addresses");
+        address_tree = proto_item_add_subtree(item, ett_addresses);
+    }
+
+    start = asn1p->pointer + item_len;
+
+    while(start > asn1p->pointer) {
+        dissect_type_value_pair(asn1p, &offset,
+                                &address_type, &item_len, &tmp_pos1,
+                                &str, &str_len, &tmp_pos2);
+
+        if (address_tree) {
+            proto_tree_add_text(address_tree, NullTVB, tmp_pos1,
+                                item_len, "Type: %s",
+                                val_to_str(address_type, krb5_address_types,
+                                           "Unknown address type %#x"));
+            switch(address_type) {
+                case KRB5_ADDR_IPv4:
+                    proto_tree_add_text(address_tree, NullTVB, tmp_pos2,
+                                        str_len, "Value: %d.%d.%d.%d",
+                                        str[0], str[1], str[2], str[3]);
+                    break;
+                    
+                default:
+                    proto_tree_add_text(address_tree, NullTVB, tmp_pos2,
+                                        str_len, "Value: %s",
+                                        bytes_to_str(str, str_len));
+            }
+        }
+    }
+    
+    if (inoff)
+        *inoff = offset;
+}
+
+void
+dissect_EncryptedData(char *title, ASN1_SCK *asn1p, frame_data *fd,
+                      proto_tree *tree, int *inoff) {
+    proto_tree *encr_tree = NULL;
+    int offset = 0;
+
+    const guchar *start;
+    guint cls, con, tag;
+    guint item_len;
+    int ret;
+
+    proto_item *item = NULL;
+    guint length;
+    gboolean def;
+    int val;
+
+    guchar *data;
+
+    if (inoff)
+        offset = *inoff;
+    
+    KRB_HEAD_DECODE_OR_DIE("encrypted data section");
+
+    if (tree) {
+        item = proto_tree_add_text(tree, NullTVB, *inoff, item_len,
+                                   "Encrypted Data: %s", title);
+        encr_tree = proto_item_add_subtree(item, ett_princ);
+    }
+
+    /* type */
+    KRB_HEAD_DECODE_OR_DIE("encryption type");
+    KRB_DECODE_OR_DIE("encr-type", asn1_int32_decode, val);
+
+    if (encr_tree) {
+        proto_tree_add_text(encr_tree, NullTVB, offset, length,
+                            "Type: %s",
+                            val_to_str(val, krb5_encryption_types,
+                                       "Unknown encryption type %#x"));
+    }
+    offset += length;
+
+    /* kvno */
+    KRB_HEAD_DECODE_OR_DIE("kvno-wrap");
+    KRB_DECODE_OR_DIE("kvno", asn1_int32_decode, val);
+
+    if (encr_tree) {
+        proto_tree_add_text(encr_tree, NullTVB, offset, length,
+                            "KVNO: %d", val);
+    }
+    offset += length;
+
+    KRB_HEAD_DECODE_OR_DIE("cipher-wrap");
+    KRB_HEAD_DECODE_OR_DIE("cipher");
+    asn1_octet_string_value_decode (asn1p, item_len, &data);
+
+    if (encr_tree) {
+        proto_tree_add_text(encr_tree, NullTVB, offset, length,
+                            "Cipher: %s", bytes_to_str(data, item_len));
+    }
+    offset += item_len;
+    
+    if (inoff)
+        *inoff = offset;
+}
+
+void
+dissect_ticket(char *title, ASN1_SCK *asn1p, frame_data *fd, proto_tree *tree,
+               int *inoff) {
+/*
+   Ticket ::=                    [APPLICATION 1] SEQUENCE {
+                                 tkt-vno[0]                   INTEGER,
+                                 realm[1]                     Realm,
+                                 sname[2]                     PrincipalName,
+                                 enc-part[3]                  EncryptedData
+   }
+*/
+    proto_tree *ticket_tree = NULL;
+    int offset = 0;
+
+    const guchar *start;
+    guint cls, con, tag;
+    guint item_len;
+    int ret;
+
+    proto_item *item = NULL;
+    guint length;
+    gboolean def;
+    int val;
+
+    int str_len;
+    guchar *str;
+
+    if (inoff)
+        offset = *inoff;
+    
+    KRB_HEAD_DECODE_OR_DIE("ticket section");
+    KRB_HEAD_DECODE_OR_DIE("ticket sequence");
+
+    if (tree) {
+        item = proto_tree_add_text(tree, NullTVB, *inoff, item_len,
+                                   "Ticket");
+        ticket_tree = proto_item_add_subtree(item, ett_ticket);
+    }
+
+    /* type */
+    KRB_HEAD_DECODE_OR_DIE("ticket type");
+    KRB_DECODE_OR_DIE("ticket-type", asn1_int32_decode, val);
+
+    if (ticket_tree) {
+        proto_tree_add_text(ticket_tree, NullTVB, offset, length,
+                            "Version: %d", val);
+    }
+    offset += length;
+
+    /* realm name */
+    KRB_HEAD_DECODE_OR_DIE("realm");
+    dissect_GeneralString(asn1p, &str, &str_len, &item_len);
+    offset += item_len - str_len;
+    if (ticket_tree) {
+        proto_tree_add_text(ticket_tree, NullTVB, offset, str_len,
+                            "Realm: %.*s", str_len, str);
+    }
+    offset += str_len;
+
+    /* server name (sname) */
+    KRB_HEAD_DECODE_OR_DIE("sname");
+    dissect_PrincipalName("Service Name", asn1p, fd, ticket_tree, &offset);
+
+    /* ticket */
+    KRB_HEAD_DECODE_OR_DIE("enc-part");
+    dissect_EncryptedData("ticket data", asn1p, fd, ticket_tree, &offset);
+
+    if (inoff)
+        *inoff = offset;
+}
+
+
+void
+proto_register_kerberos(void) {
+    static hf_register_info hf[] = {
+    };
+    static gint *ett[] = {
+        &ett_kerberos,
+        &ett_preauth,
+        &ett_request,
+        &ett_princ,
+        &ett_encrypted,
+        &ett_ticket,
+        &ett_addresses,
+        &ett_etype,
+    };
+    proto_kerberos = proto_register_protocol("Kerberos", "kerberos");
+    proto_register_field_array(proto_kerberos, hf, array_length(hf));
+    proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_kerberos(void)
+{
+       old_dissector_add("udp.port", UDP_PORT_KERBEROS, dissect_kerberos);
+       old_dissector_add("tcp.port", TCP_PORT_KERBEROS, dissect_kerberos);
+}
+
+/*
+
+  MISC definitions from RFC1510:
+  
+   KerberosTime ::=   GeneralizedTime
+   Realm ::=           GeneralString
+   PrincipalName ::=   SEQUENCE {
+                       name-type[0]     INTEGER,
+                       name-string[1]   SEQUENCE OF GeneralString
+   }
+    HostAddress ::=     SEQUENCE  {
+                        addr-type[0]             INTEGER,
+                        address[1]               OCTET STRING
+    }
+
+    HostAddresses ::=   SEQUENCE OF SEQUENCE {
+                        addr-type[0]             INTEGER,
+                        address[1]               OCTET STRING
+    }
+
+    AS-REQ ::=         [APPLICATION 10] KDC-REQ
+    TGS-REQ ::=        [APPLICATION 12] KDC-REQ
+    
+    KDC-REQ ::=        SEQUENCE {
+           pvno[1]               INTEGER,
+           msg-type[2]           INTEGER,
+           padata[3]             SEQUENCE OF PA-DATA OPTIONAL,
+           req-body[4]           KDC-REQ-BODY
+    }
+
+    PA-DATA ::=        SEQUENCE {
+           padata-type[1]        INTEGER,
+           padata-value[2]       OCTET STRING,
+                         -- might be encoded AP-REQ
+    }
+
+KDC-REQ-BODY ::=   SEQUENCE {
+            kdc-options[0]       KDCOptions,
+            cname[1]             PrincipalName OPTIONAL,
+                         -- Used only in AS-REQ
+            realm[2]             Realm, -- Server's realm
+                         -- Also client's in AS-REQ
+            sname[3]             PrincipalName OPTIONAL,
+            from[4]              KerberosTime OPTIONAL,
+            till[5]              KerberosTime,
+            rtime[6]             KerberosTime OPTIONAL,
+            nonce[7]             INTEGER,
+            etype[8]             SEQUENCE OF INTEGER, -- EncryptionType,
+                         -- in preference order
+            addresses[9]         HostAddresses OPTIONAL,
+            enc-authorization-data[10]   EncryptedData OPTIONAL,
+                         -- Encrypted AuthorizationData encoding
+            additional-tickets[11]       SEQUENCE OF Ticket OPTIONAL
+}
+
+   AS-REP ::=    [APPLICATION 11] KDC-REP
+   TGS-REP ::=   [APPLICATION 13] KDC-REP
+
+   KDC-REP ::=   SEQUENCE {
+                 pvno[0]                    INTEGER,
+                 msg-type[1]                INTEGER,
+                 padata[2]                  SEQUENCE OF PA-DATA OPTIONAL,
+                 crealm[3]                  Realm,
+                 cname[4]                   PrincipalName,
+                 ticket[5]                  Ticket,
+                 enc-part[6]                EncryptedData
+   }
+
+   EncASRepPart ::=    [APPLICATION 25[25]] EncKDCRepPart
+   EncTGSRepPart ::=   [APPLICATION 26] EncKDCRepPart
+
+   EncKDCRepPart ::=   SEQUENCE {
+               key[0]                       EncryptionKey,
+               last-req[1]                  LastReq,
+               nonce[2]                     INTEGER,
+               key-expiration[3]            KerberosTime OPTIONAL,
+               flags[4]                     TicketFlags,
+               authtime[5]                  KerberosTime,
+               starttime[6]                 KerberosTime OPTIONAL,
+               endtime[7]                   KerberosTime,
+               renew-till[8]                KerberosTime OPTIONAL,
+               srealm[9]                    Realm,
+               sname[10]                    PrincipalName,
+               caddr[11]                    HostAddresses OPTIONAL
+   }
+
+   Ticket ::=                    [APPLICATION 1] SEQUENCE {
+                                 tkt-vno[0]                   INTEGER,
+                                 realm[1]                     Realm,
+                                 sname[2]                     PrincipalName,
+                                 enc-part[3]                  EncryptedData
+   }
+
+
+*/
diff --git a/packet-kerberos.h b/packet-kerberos.h
new file mode 100644 (file)
index 0000000..473f158
--- /dev/null
@@ -0,0 +1,40 @@
+/* packet-kerberos.h
+ * Exported routines for Kerberos
+ * Wes Hardaker (c) 2000
+ * wjhardaker@ucdavis.edu
+ *
+ * $Id: packet-kerberos.h,v 1.1 2000/08/11 03:32:44 guy Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Didier Jorand
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+void dissect_kerberos(const u_char *, int, frame_data *, proto_tree *);
+void dissect_PrincipalName(char *title, ASN1_SCK *asn1p, frame_data *fd,
+                            proto_tree *tree, int *offset);
+void dissect_GeneralString(ASN1_SCK *asn1p, guchar **where, guint *item_len,
+                           guint *pkt_len);
+void dissect_ticket(char *title, ASN1_SCK *asn1p, frame_data *fd,
+                    proto_tree *tree, int *inoff);
+void dissect_EncryptedData(char *title, ASN1_SCK *asn1p, frame_data *fd,
+                           proto_tree *tree, int *inoff);
+void dissect_Addresses(char *title, ASN1_SCK *asn1p, frame_data *fd,
+                       proto_tree *tree, int *inoff);
+
+
+