aboutsummaryrefslogtreecommitdiffstats
path: root/packet-kerberos.c
diff options
context:
space:
mode:
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>2000-08-11 03:32:53 +0000
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>2000-08-11 03:32:53 +0000
commitbd329f5fdb230a5cafa077ee2fea5aee0664c095 (patch)
treeea3940a3c02e34a92861333b1e24318331e6be5c /packet-kerberos.c
parent78e1ee0e252f1028188279ab556cf1a1510bcabe (diff)
Kerberos 5 dissector, from Wes Hardaker.
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@2250 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'packet-kerberos.c')
-rw-r--r--packet-kerberos.c944
1 files changed, 944 insertions, 0 deletions
diff --git a/packet-kerberos.c b/packet-kerberos.c
new file mode 100644
index 0000000000..a2e95fa731
--- /dev/null
+++ b/packet-kerberos.c
@@ -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
+ }
+
+
+*/