As the gtk2 directory is no longer needed (GTK1 and 2 are using the same sources...
[obnox/wireshark/wip.git] / packet-kerberos.c
index 0e32c96b17fdf32e4b26ab902b6f1fc32e8726a6..a84046d1799ea57c33f74ac698376fdc3d01c77c 100644 (file)
  *
  * and
  *
- *     http://www.ietf.org/internet-drafts/draft-ietf-krb-wg-kerberos-clarifications-03.txt
+ *     http://www.ietf.org/internet-drafts/draft-ietf-krb-wg-kerberos-clarifications-05.txt
  *
- * $Id: packet-kerberos.c,v 1.52 2004/03/26 00:21:53 guy Exp $
+ * and
+ *
+ *      http://www.ietf.org/internet-drafts/draft-ietf-krb-wg-kerberos-referrals-03.txt
+ *
+ * Some structures from RFC2630
+ *
+ * $Id$
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -52,6 +58,7 @@
 
 #include <epan/strutil.h>
 
+#include "packet-kerberos.h"
 #include "packet-netbios.h"
 #include "packet-tcp.h"
 #include "prefs.h"
@@ -61,6 +68,9 @@
 #include "packet-dcerpc-netlogon.h"
 #include "packet-dcerpc.h"
 
+#include "asn1.h"              /* for "subid_t" */
+#include "packet-gssapi.h"
+
 #define UDP_PORT_KERBEROS              88
 #define TCP_PORT_KERBEROS              88
 
@@ -82,6 +92,7 @@ static gint hf_krb_w2k_pac_type = -1;
 static gint hf_krb_w2k_pac_size = -1;
 static gint hf_krb_w2k_pac_offset = -1;
 static gint hf_krb_padata = -1;
+static gint hf_krb_contentinfo_contenttype = -1;
 static gint hf_krb_error_code = -1;
 static gint hf_krb_ticket = -1;
 static gint hf_krb_AP_REP_enc = -1;
@@ -105,24 +116,33 @@ static gint hf_krb_encrypted_KDC_REP_data = -1;
 static gint hf_krb_PA_DATA_type = -1;
 static gint hf_krb_PA_DATA_value = -1;
 static gint hf_krb_etype_info_salt = -1;
+static gint hf_krb_SAFE_BODY_user_data = -1;
 static gint hf_krb_realm = -1;
 static gint hf_krb_crealm = -1;
 static gint hf_krb_sname = -1;
 static gint hf_krb_cname = -1;
 static gint hf_krb_name_string = -1;
+static gint hf_krb_provsrv_location = -1;
 static gint hf_krb_e_text = -1;
 static gint hf_krb_name_type = -1;
+static gint hf_krb_lr_type = -1;
 static gint hf_krb_from = -1;
 static gint hf_krb_till = -1;
 static gint hf_krb_authtime = -1;
+static gint hf_krb_patimestamp = -1;
+static gint hf_krb_SAFE_BODY_timestamp = -1;
+static gint hf_krb_pausec = -1;
+static gint hf_krb_lr_time = -1;
 static gint hf_krb_starttime = -1;
 static gint hf_krb_endtime = -1;
+static gint hf_krb_key_expire = -1;
 static gint hf_krb_renew_till = -1;
 static gint hf_krb_rtime = -1;
 static gint hf_krb_ctime = -1;
 static gint hf_krb_cusec = -1;
 static gint hf_krb_stime = -1;
 static gint hf_krb_susec = -1;
+static gint hf_krb_SAFE_BODY_usec = -1;
 static gint hf_krb_nonce = -1;
 static gint hf_krb_transitedtype = -1;
 static gint hf_krb_transitedcontents = -1;
@@ -134,6 +154,7 @@ static gint hf_krb_adtype = -1;
 static gint hf_krb_advalue = -1;
 static gint hf_krb_etype = -1;
 static gint hf_krb_etypes = -1;
+static gint hf_krb_LastReqs = -1;
 static gint hf_krb_IF_RELEVANT = -1;
 static gint hf_krb_addr_type = -1;
 static gint hf_krb_address_ip = -1;
@@ -149,8 +170,12 @@ static gint hf_krb_subkey = -1;
 static gint hf_krb_seq_number = -1;
 static gint hf_krb_EncTicketPart = -1;
 static gint hf_krb_EncAPRepPart = -1;
+static gint hf_krb_EncKDCRepPart = -1;
+static gint hf_krb_LastReq = -1;
 static gint hf_krb_Authenticator = -1;
 static gint hf_krb_Checksum = -1;
+static gint hf_krb_signedAuthPack = -1;
+static gint hf_krb_s_address = -1;
 static gint hf_krb_HostAddress = -1;
 static gint hf_krb_HostAddresses = -1;
 static gint hf_krb_APOptions = -1;
@@ -178,6 +203,7 @@ static gint hf_krb_KDCOptions_proxy = -1;
 static gint hf_krb_KDCOptions_allow_postdate = -1;
 static gint hf_krb_KDCOptions_postdated = -1;
 static gint hf_krb_KDCOptions_renewable = -1;
+static gint hf_krb_KDCOptions_canonicalize = -1;
 static gint hf_krb_KDCOptions_opt_hardware_auth = -1;
 static gint hf_krb_KDCOptions_disable_transited_check = -1;
 static gint hf_krb_KDCOptions_renewable_ok = -1;
@@ -193,6 +219,7 @@ static gint hf_krb_ticket_enc = -1;
 static gint ett_krb_kerberos = -1;
 static gint ett_krb_TransitedEncoding = -1;
 static gint ett_krb_PAC_LOGON_INFO = -1;
+static gint ett_krb_signedAuthPack = -1;
 static gint ett_krb_PAC_CREDENTIAL_TYPE = -1;
 static gint ett_krb_PAC_SERVER_CHECKSUM = -1;
 static gint ett_krb_PAC_PRIVSVR_CHECKSUM = -1;
@@ -200,6 +227,8 @@ static gint ett_krb_PAC_CLIENT_INFO_TYPE = -1;
 static gint ett_krb_KDC_REP_enc = -1;
 static gint ett_krb_EncTicketPart = -1;
 static gint ett_krb_EncAPRepPart = -1;
+static gint ett_krb_EncKDCRepPart = -1;
+static gint ett_krb_LastReq = -1;
 static gint ett_krb_Authenticator = -1;
 static gint ett_krb_Checksum = -1;
 static gint ett_krb_key = -1;
@@ -210,9 +239,11 @@ static gint ett_krb_cname = -1;
 static gint ett_krb_AP_REP_enc = -1;
 static gint ett_krb_padata = -1;
 static gint ett_krb_etypes = -1;
+static gint ett_krb_LastReqs = -1;
 static gint ett_krb_IF_RELEVANT = -1;
 static gint ett_krb_PA_DATA_tree = -1;
 static gint ett_krb_PAC = -1;
+static gint ett_krb_s_address = -1;
 static gint ett_krb_HostAddress = -1;
 static gint ett_krb_HostAddresses = -1;
 static gint ett_krb_authenticator_enc = -1;
@@ -233,7 +264,24 @@ guint32 krb5_errorcode;
 static int do_col_info;
 
 
+static void
+call_kerberos_callbacks(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int tag)
+{
+       kerberos_callbacks *cb=(kerberos_callbacks *)pinfo->private_data;
 
+       if(!cb){
+               return;
+       }
+
+       while(cb->tag){
+               if(cb->tag==tag){
+                       cb->callback(pinfo, tvb, tree);
+                       return;
+               }
+               cb++;
+       }
+       return;
+}
 
 
 
@@ -404,6 +452,8 @@ printf("woohoo decrypted keytype:%d in frame:%d\n", keytype, pinfo->fd->num);
 #define KRB5_MSG_SAFE                  20      /* KRB-SAFE type */
 #define KRB5_MSG_PRIV                  21      /* KRB-PRIV type */
 #define KRB5_MSG_CRED                  22      /* KRB-CRED type */
+#define KRB5_MSG_ENC_AS_REP_PART       25      /* EncASRepPart */
+#define KRB5_MSG_ENC_TGS_REP_PART      26      /* EncTGSRepPart */
 #define KRB5_MSG_ENC_AP_REP_PART       27      /* EncAPRepPart */
 #define KRB5_MSG_ERROR                 30      /* KRB-ERROR type */
 
@@ -426,11 +476,49 @@ printf("woohoo decrypted keytype:%d in frame:%d\n", keytype, pinfo->fd->num);
 #define KRB5_ENCTYPE_DES3_CBC_SHA        5
 #define KRB5_ENCTYPE_DES3_CBC_RAW        6
 #define KRB5_ENCTYPE_DES_HMAC_SHA1       8
+#define KRB5_ENCTYPE_DSA_SHA1_CMS        9
+#define KRB5_ENCTYPE_RSA_MD5_CMS         10
+#define KRB5_ENCTYPE_RSA_SHA1_CMS        11
+#define KRB5_ENCTYPE_RC2_CBC_ENV         12
+#define KRB5_ENCTYPE_RSA_ENV             13
+#define KRB5_ENCTYPE_RSA_ES_OEAP_ENV     14
+#define KRB5_ENCTYPE_DES_EDE3_CBC_ENV    15
 #define KRB5_ENCTYPE_DES3_CBC_SHA1       16
+#define KRB5_ENCTYPE_DES_CBC_MD5_NT      20
 #define KERB_ENCTYPE_RC4_HMAC            23 
 #define KERB_ENCTYPE_RC4_HMAC_EXP        24
 #define KRB5_ENCTYPE_UNKNOWN                0x1ff
 #define KRB5_ENCTYPE_LOCAL_DES3_HMAC_SHA1   0x7007
+#define KRB5_ENCTYPE_RC4_PLAIN_EXP     0xffffff73
+#define KRB5_ENCTYPE_RC4_PLAIN         0xffffff74
+#define KRB5_ENCTYPE_RC4_PLAIN_OLD_EXP 0xffffff78
+#define KRB5_ENCTYPE_RC4_HMAC_OLD_EXP  0xffffff79
+#define KRB5_ENCTYPE_RC4_PLAIN_OLD     0xffffff7a
+#define KRB5_ENCTYPE_RC4_HMAC_OLD      0xffffff7b
+#define KRB5_ENCTYPE_DES_PLAIN         0xffffff7c
+#define KRB5_ENCTYPE_RC4_SHA           0xffffff7d
+#define KRB5_ENCTYPE_RC4_LM            0xffffff7e
+#define KRB5_ENCTYPE_RC4_PLAIN2                0xffffff7f
+#define KRB5_ENCTYPE_RC4_MD4           0xffffff80
+
+/* checksum types */
+#define KRB5_CHKSUM_NONE                0
+#define KRB5_CHKSUM_CRC32               1
+#define KRB5_CHKSUM_MD4                 2
+#define KRB5_CHKSUM_KRB_DES_MAC         4
+#define KRB5_CHKSUM_KRB_DES_MAC_K       5
+#define KRB5_CHKSUM_MD5                 7
+#define KRB5_CHKSUM_MD5_DES             8
+#define KRB5_CHKSUM_HMAC_MD5            0xffffff76
+#define KRB5_CHKSUM_MD5_HMAC            0xffffff77
+#define KRB5_CHKSUM_RC4_MD5             0xffffff78
+#define KRB5_CHKSUM_MD25                0xffffff79
+#define KRB5_CHKSUM_DES_MAC_MD5         0xffffff7a
+#define KRB5_CHKSUM_DES_MAC             0xffffff7b
+#define KRB5_CHKSUM_REAL_CRC32          0xffffff7c
+#define KRB5_CHKSUM_SHA1                0xffffff7d
+#define KRB5_CHKSUM_LM                  0xffffff7e
+
 
 /*
  * For KERB_ENCTYPE_RC4_HMAC and KERB_ENCTYPE_RC4_HMAC_EXP, see
@@ -472,15 +560,34 @@ printf("woohoo decrypted keytype:%d in frame:%d\n", keytype, pinfo->fd->num);
 #define KRB5_TD_APP_DEFINED_ERROR      106
 #define KRB5_TD_REQ_NONCE              107
 #define KRB5_TD_REQ_SEQ                108
-#define KRB5_PA_PAC_REQUEST            128
+/* preauthentication types >127 (i.e. negative ones) are app specific.
+   hopefully there will be no collissions here or we will have to
+   come up with something better
+*/
+#define KRB5_PA_PAC_REQUEST            128     /* MS extension */
+#define KRB5_PA_PROV_SRV_LOCATION      255     /* packetcable stuff */
 
 /* Principal name-type */
-#define KRB5_NT_UNKNOWN     0
-#define KRB5_NT_PRINCIPAL   1
-#define KRB5_NT_SRV_INST    2  
-#define KRB5_NT_SRV_HST     3
-#define KRB5_NT_SRV_XHST    4
-#define KRB5_NT_UID     5
+#define KRB5_NT_UNKNOWN        0
+#define KRB5_NT_PRINCIPAL      1
+#define KRB5_NT_SRV_INST       2       
+#define KRB5_NT_SRV_HST        3
+#define KRB5_NT_SRV_XHST       4
+#define KRB5_NT_UID            5
+#define KRB5_NT_X500_PRINCIPAL 6
+#define KRB5_NT_SMTP_NAME      7
+#define KRB5_NT_ENTERPRISE    10
+
+/*
+ * MS specific name types, from
+ *
+ *     http://msdn.microsoft.com/library/en-us/security/security/kerb_external_name.asp
+ */
+#define KRB5_NT_MS_PRINCIPAL           -128    
+#define KRB5_NT_MS_PRINCIPAL_AND_SID   -129
+#define KRB5_NT_ENT_PRINCIPAL_AND_SID  -130
+#define KRB5_NT_PRINCIPAL_AND_SID      -131
+#define KRB5_NT_SRV_INST_AND_SID       -132
 
 /* error table constants */
 /* I prefixed the krb5_err.et constant names with KRB5_ET_ for these */
@@ -651,6 +758,14 @@ static const value_string krb5_princ_types[] = {
     { KRB5_NT_SRV_HST              , "Service and Host" },
     { KRB5_NT_SRV_XHST             , "Service and Host Components" },
     { KRB5_NT_UID                  , "Unique ID" },
+    { KRB5_NT_X500_PRINCIPAL       , "Encoded X.509 Distinguished Name" },
+    { KRB5_NT_SMTP_NAME            , "SMTP Name" },
+    { KRB5_NT_ENTERPRISE           , "Enterprise Name" },
+    { KRB5_NT_MS_PRINCIPAL         , "NT 4.0 style name (MS specific)" },
+    { KRB5_NT_MS_PRINCIPAL_AND_SID , "NT 4.0 style name with SID (MS specific)"},
+    { KRB5_NT_ENT_PRINCIPAL_AND_SID, "UPN and SID (MS specific)"},
+    { KRB5_NT_PRINCIPAL_AND_SID    , "Principal name and SID (MS specific)"},
+    { KRB5_NT_SRV_INST_AND_SID     , "SPN and SID (MS specific)"},
     { 0                            , NULL },
 };
 
@@ -687,6 +802,7 @@ static const value_string krb5_preauthentication_types[] = {
     { KRB5_TD_REQ_NONCE            , "TD-REQ-NONCE" },
     { KRB5_TD_REQ_SEQ              , "TD-REQ-SEQ" },
     { KRB5_PA_PAC_REQUEST          , "PA-PAC-REQUEST" },
+    { KRB5_PA_PROV_SRV_LOCATION    , "PA-PROV-SRV-LOCATION" },
     { 0                            , NULL },
 };
 
@@ -699,14 +815,52 @@ static const value_string krb5_encryption_types[] = {
     { KRB5_ENCTYPE_DES3_CBC_SHA   , "des3-cbc-sha" },
     { KRB5_ENCTYPE_DES3_CBC_RAW   , "des3-cbc-raw" },
     { KRB5_ENCTYPE_DES_HMAC_SHA1  , "des-hmac-sha1" },
+    { KRB5_ENCTYPE_DSA_SHA1_CMS   , "dsa-sha1-cms" },
+    { KRB5_ENCTYPE_RSA_MD5_CMS    , "rsa-md5-cms" },
+    { KRB5_ENCTYPE_RSA_SHA1_CMS   , "rsa-sha1-cms" },
+    { KRB5_ENCTYPE_RC2_CBC_ENV    , "rc2-cbc-env" },
+    { KRB5_ENCTYPE_RSA_ENV        , "rsa-env" },
+    { KRB5_ENCTYPE_RSA_ES_OEAP_ENV, "rsa-es-oeap-env" },
+    { KRB5_ENCTYPE_DES_EDE3_CBC_ENV, "des-ede3-cbc-env" },
     { KRB5_ENCTYPE_DES3_CBC_SHA1  , "des3-cbc-sha1" },
+    { KRB5_ENCTYPE_DES_CBC_MD5_NT  , "des-cbc-md5-nt" },
     { KERB_ENCTYPE_RC4_HMAC       , "rc4-hmac" },
     { KERB_ENCTYPE_RC4_HMAC_EXP   , "rc4-hmac-exp" },
     { KRB5_ENCTYPE_UNKNOWN        , "unknown" },
     { KRB5_ENCTYPE_LOCAL_DES3_HMAC_SHA1    , "local-des3-hmac-sha1" },
+    { KRB5_ENCTYPE_RC4_PLAIN_EXP  , "rc4-plain-exp" },
+    { KRB5_ENCTYPE_RC4_PLAIN      , "rc4-plain" },
+    { KRB5_ENCTYPE_RC4_PLAIN_OLD_EXP, "rc4-plain-old-exp" },
+    { KRB5_ENCTYPE_RC4_HMAC_OLD_EXP, "rc4-hmac-old-exp" },
+    { KRB5_ENCTYPE_RC4_PLAIN_OLD  , "rc4-plain-old" },
+    { KRB5_ENCTYPE_RC4_HMAC_OLD   , "rc4-hmac-old" },
+    { KRB5_ENCTYPE_DES_PLAIN      , "des-plain" },
+    { KRB5_ENCTYPE_RC4_SHA        , "rc4-sha" },
+    { KRB5_ENCTYPE_RC4_LM         , "rc4-lm" },
+    { KRB5_ENCTYPE_RC4_PLAIN2     , "rc4-plain2" },
+    { KRB5_ENCTYPE_RC4_MD4        , "rc4-md4" },
     { 0                           , NULL },
 };
 
+static const value_string krb5_checksum_types[] = {
+    { KRB5_CHKSUM_NONE            , "none" },
+    { KRB5_CHKSUM_CRC32           , "crc32" },
+    { KRB5_CHKSUM_MD4             , "md4" },
+    { KRB5_CHKSUM_KRB_DES_MAC     , "krb-des-mac" },
+    { KRB5_CHKSUM_KRB_DES_MAC_K   , "krb-des-mac-k" },
+    { KRB5_CHKSUM_MD5             , "md5" },
+    { KRB5_CHKSUM_MD5_DES         , "md5-des" },
+    { KRB5_CHKSUM_HMAC_MD5        , "hmac-md5" },
+    { KRB5_CHKSUM_MD5_HMAC        , "md5-hmac" },
+    { KRB5_CHKSUM_RC4_MD5         , "rc5-md5" },
+    { KRB5_CHKSUM_MD25            , "md25" },
+    { KRB5_CHKSUM_DES_MAC_MD5     , "des-mac-md5" },
+    { KRB5_CHKSUM_DES_MAC         , "des-mac" },
+    { KRB5_CHKSUM_REAL_CRC32      , "real-crc32" },
+    { KRB5_CHKSUM_SHA1            , "sha1" },
+    { KRB5_CHKSUM_LM              , "lm" },
+    { 0                           , NULL },
+};
 
 #define KRB5_AD_IF_RELEVANT                    1
 #define KRB5_AD_INTENDED_FOR_SERVER            2
@@ -765,6 +919,8 @@ static const value_string krb5_msg_types[] = {
        { KRB5_MSG_SAFE,                "KRB-SAFE" },
        { KRB5_MSG_PRIV,                "KRB-PRIV" },
        { KRB5_MSG_CRED,                "KRB-CRED" },
+       { KRB5_MSG_ENC_AS_REP_PART,     "EncASRepPart" },
+       { KRB5_MSG_ENC_TGS_REP_PART,    "EncTGSRepPart" },
        { KRB5_MSG_ENC_AP_REP_PART,     "EncAPRepPart" },
        { KRB5_MSG_ERROR,               "KRB-ERROR" },
         { 0, NULL },
@@ -777,10 +933,12 @@ static int dissect_krb5_application_choice(packet_info *pinfo, proto_tree *tree,
 static int dissect_krb5_Authenticator(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
 static int dissect_krb5_EncTicketPart(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
 static int dissect_krb5_EncAPRepPart(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
+static int dissect_krb5_EncKDCRepPart(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
 static int dissect_krb5_KDC_REQ(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
 static int dissect_krb5_KDC_REP(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
 static int dissect_krb5_AP_REQ(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
 static int dissect_krb5_AP_REP(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
+static int dissect_krb5_SAFE(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
 static int dissect_krb5_PRIV(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
 static int dissect_krb5_ERROR(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
 
@@ -793,7 +951,10 @@ static const ber_choice kerberos_applications_choice[] = {
        { KRB5_MSG_TGS_REP,     BER_CLASS_APP,  KRB5_MSG_TGS_REP,       0,      dissect_krb5_KDC_REP },
        { KRB5_MSG_AP_REQ,      BER_CLASS_APP,  KRB5_MSG_AP_REQ,        0,      dissect_krb5_AP_REQ },
        { KRB5_MSG_AP_REP,      BER_CLASS_APP,  KRB5_MSG_AP_REP,        0,      dissect_krb5_AP_REP },
+       { KRB5_MSG_ENC_AS_REP_PART, BER_CLASS_APP, KRB5_MSG_ENC_AS_REP_PART, 0, dissect_krb5_EncKDCRepPart },
+       { KRB5_MSG_ENC_TGS_REP_PART, BER_CLASS_APP, KRB5_MSG_ENC_TGS_REP_PART, 0, dissect_krb5_EncKDCRepPart },
        { KRB5_MSG_ENC_AP_REP_PART, BER_CLASS_APP, KRB5_MSG_ENC_AP_REP_PART, 0, dissect_krb5_EncAPRepPart },
+       { KRB5_MSG_SAFE,        BER_CLASS_APP,  KRB5_MSG_SAFE,          0,      dissect_krb5_SAFE },
        { KRB5_MSG_PRIV,        BER_CLASS_APP,  KRB5_MSG_PRIV,          0,      dissect_krb5_PRIV },
        { KRB5_MSG_ERROR,       BER_CLASS_APP,  KRB5_MSG_ERROR,         0,      dissect_krb5_ERROR },
        { 0, 0, 0, 0, NULL }
@@ -859,6 +1020,10 @@ static const true_false_string krb5_kdcoptions_renewable = {
        "This ticket is RENEWABLE",
        "This ticket is NOT renewable"
 };
+static const true_false_string krb5_kdcoptions_canonicalize = {
+       "This is a request for a CANONICALIZED ticket",
+       "This is NOT a canonicalized ticket request"
+};
 static const true_false_string krb5_kdcoptions_disable_transited_check = {
        "Transited checking is DISABLED",
        "Transited checking is NOT disabled"
@@ -889,6 +1054,7 @@ static int* KDCOptions_bits[] = {
   &hf_krb_KDCOptions_postdated,   
   &hf_krb_KDCOptions_renewable,
   &hf_krb_KDCOptions_opt_hardware_auth,
+  &hf_krb_KDCOptions_canonicalize,
   &hf_krb_KDCOptions_disable_transited_check,   
   &hf_krb_KDCOptions_renewable_ok,
   &hf_krb_KDCOptions_enc_tkt_in_skey,
@@ -988,7 +1154,7 @@ dissect_krb5_etype(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offs
        if(tree){
                proto_item_append_text(tree, " %s", 
                        val_to_str(etype, krb5_encryption_types,
-                       "%#x"));
+                       "%d"));
        }
        return offset;
 }
@@ -1038,6 +1204,18 @@ dissect_krb5_AP_REP_etype(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, i
        }
        return offset;
 }
+static guint32 PA_ENC_TIMESTAMP_etype;
+static int 
+dissect_krb5_PA_ENC_TIMESTAMP_etype(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_etype, &PA_ENC_TIMESTAMP_etype);
+       if(tree){
+               proto_item_append_text(tree, " %s", 
+                       val_to_str(PA_ENC_TIMESTAMP_etype, krb5_encryption_types,
+                       "%#x"));
+       }
+       return offset;
+}
 
 
 /*
@@ -1090,8 +1268,8 @@ static int dissect_krb5_address(packet_info *pinfo, proto_tree *tree, tvbuff_t *
 
        /* push it up two levels in the decode pane */
        if(it){
-               proto_item_append_text(proto_item_get_parent(it), "  %s",address_str);
-               proto_item_append_text(proto_item_get_parent_nth(it, 2), "  %s",address_str);
+               proto_item_append_text(proto_item_get_parent(it), " %s",address_str);
+               proto_item_append_text(proto_item_get_parent_nth(it, 2), " %s",address_str);
        }
 
        offset+=len;
@@ -1110,6 +1288,14 @@ dissect_krb5_HostAddress(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, in
 
        return offset;
 }
+static int
+dissect_krb5_s_address(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+
+       offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, HostAddress_sequence, hf_krb_s_address, ett_krb_s_address);
+
+       return offset;
+}
 
 /*
  *  HostAddresses ::=   SEQUENCE OF SEQUENCE {
@@ -1145,6 +1331,9 @@ dissect_krb5_msg_type(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int o
        }
        do_col_info=FALSE;
 
+       /* append the application type to the subtree */
+       proto_item_append_text(tree, " %s", val_to_str(msgtype, krb5_msg_types, "Unknown:0x%x"));
+
        return offset;
 }
 
@@ -1165,13 +1354,14 @@ dissect_krb5_pvno(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offse
  *                     name-string[1]   SEQUENCE OF GeneralString
  * }
  */
-static guint32 name_type;
 static int 
 dissect_krb5_name_type(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
 {
+       guint32 name_type;
+
        offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_name_type, &name_type);
        if(tree){
-               proto_item_append_text(tree, "  (%s):", 
+               proto_item_append_text(tree, " (%s):", 
                        val_to_str(name_type, krb5_princ_types,
                        "Unknown:%d"));
        }
@@ -1262,6 +1452,102 @@ dissect_krb5_PA_PAC_REQUEST(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
 
 
 
+static int
+dissect_krb5_SignedData(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset)
+{
+/*qqq*/
+       return offset;
+}
+
+
+static char ContentType[64]; /*64 chars should be long enough */
+static int
+dissect_krb5_ContentInfo_ContentType(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       ContentType[0]=0;
+       offset=dissect_ber_object_identifier(TRUE, pinfo, tree, tvb, offset, hf_krb_contentinfo_contenttype, ContentType);
+
+       return offset;
+}
+
+/* the content of this structure depends on the ContentType object identifier */
+static int
+dissect_krb5_ContentInfo_content(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       if(!strcmp(ContentType, "1.2.840.113549.1.7.2")){
+               offset=dissect_krb5_SignedData(pinfo, tree, tvb, offset);
+       } else {
+               proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset), "ContentInfo: dont know how to parse this type yet.");
+       }
+
+       return offset;
+}
+
+static ber_sequence ContentInfo_sequence[] = {
+       { BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_krb5_ContentInfo_ContentType },
+       { BER_CLASS_CON, 0, 0, dissect_krb5_ContentInfo_content },
+       { 0, 0, 0, NULL }
+};
+
+static int
+dissect_krb5_PA_PK_AS_REQ_signedAuthPack(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, ContentInfo_sequence, hf_krb_signedAuthPack, ett_krb_signedAuthPack);
+
+       return offset;
+}
+
+static int
+dissect_krb5_PA_PK_AS_REQ_trustedCertifiers(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       BER_NOT_DECODED_YET("trustedCertifiers");
+
+       return offset;
+}
+static int
+dissect_krb5_PA_PK_AS_REQ_kdcCert(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       BER_NOT_DECODED_YET("kdcCert");
+
+       return offset;
+}
+static int
+dissect_krb5_PA_PK_AS_REQ_encryptionCert(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       BER_NOT_DECODED_YET("encryptionCert");
+
+       return offset;
+}
+
+
+
+static ber_sequence PA_PK_AS_REQ_sequence[] = {
+       { BER_CLASS_CON, 0, 0, dissect_krb5_PA_PK_AS_REQ_signedAuthPack },
+       { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_krb5_PA_PK_AS_REQ_trustedCertifiers },
+       { BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL, dissect_krb5_PA_PK_AS_REQ_kdcCert },
+       { BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL, dissect_krb5_PA_PK_AS_REQ_encryptionCert },
+       { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_PA_PK_AS_REQ(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+
+       offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, PA_PK_AS_REQ_sequence, -1, -1);
+
+       return offset;
+}
+
+
+static int
+dissect_krb5_PA_PROV_SRV_LOCATION(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       offset=dissect_ber_GeneralString(pinfo, tree, tvb, offset, hf_krb_provsrv_location, NULL, 0);
+
+       return offset;
+}
+
+
+
 static int
 dissect_krb5_kvno(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
 {
@@ -1282,17 +1568,73 @@ dissect_krb5_seq_number(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int
 
 
 
+#ifdef HAVE_KERBEROS
+static int 
+dissect_krb5_pausec(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_pausec, NULL);
+       return offset;
+}
+static int 
+dissect_krb5_patimestamp(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_patimestamp);
+       return offset;
+}
+static const ber_sequence PA_ENC_TS_ENC_sequence[] = {
+       { BER_CLASS_CON, 0, 0, dissect_krb5_patimestamp },
+       { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_krb5_pausec },
+       { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_decrypt_PA_ENC_TIMESTAMP (packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       guint8 *plaintext=NULL;
+       int length;
+
+       length=tvb_length_remaining(tvb, offset);
+
+       /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
+        * 7.5.1
+        * AS-REQ PA_ENC_TIMESTAMP are encrypted with usage 
+        * == 1
+        */
+       if(!plaintext){
+               plaintext=decrypt_krb5_data(pinfo, 1, length, tvb_get_ptr(tvb, offset, length), PA_ENC_TIMESTAMP_etype);
+       }
+
+       if(plaintext){
+               tvbuff_t *next_tvb;
+               next_tvb = tvb_new_real_data (plaintext,
+                                          length,
+                                          length);
+               tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+            
+               /* Add the decrypted data to the data source list. */
+               add_new_data_source(pinfo, next_tvb, "Decrypted Krb5");
+            
+
+               offset=dissect_ber_sequence(FALSE, pinfo, tree, next_tvb, 0, PA_ENC_TS_ENC_sequence, -1, -1);
+
+       }
+       return offset;
+}
+#endif
+
 
 static int
 dissect_krb5_encrypted_PA_ENC_TIMESTAMP(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
 {
-       offset=dissect_ber_octet_string(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_PA_ENC_TIMESTAMP, NULL);
+#ifdef HAVE_KERBEROS
+       offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_PA_ENC_TIMESTAMP, dissect_krb5_decrypt_PA_ENC_TIMESTAMP);
+#else
+       offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_PA_ENC_TIMESTAMP, NULL);
+#endif
        return offset;
-/*qqq*/
 }
 static ber_sequence PA_ENC_TIMESTAMP_sequence[] = {
        { BER_CLASS_CON, 0, 0, 
-               dissect_krb5_etype },
+               dissect_krb5_PA_ENC_TIMESTAMP_etype },
        { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL,
                dissect_krb5_kvno },
        { BER_CLASS_CON, 2, 0,
@@ -1354,6 +1696,7 @@ static int
 dissect_krb5_PA_DATA_type(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
 {
        offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_PA_DATA_type, &krb_PA_DATA_type);
+       krb_PA_DATA_type&=0xff; /*this is really just one single byte */
 
        if(tree){
                proto_item_append_text(tree, " %s", 
@@ -1376,9 +1719,15 @@ dissect_krb5_PA_DATA_value(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t
        case KRB5_PA_TGS_REQ:
                offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset,hf_krb_PA_DATA_value, dissect_krb5_application_choice);
                break;
+       case KRB5_PA_PK_AS_REQ:
+               offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset,hf_krb_PA_DATA_value, dissect_krb5_PA_PK_AS_REQ);
+               break;
        case KRB5_PA_PAC_REQUEST:
                offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset,hf_krb_PA_DATA_value, dissect_krb5_PA_PAC_REQUEST);
                break;
+       case KRB5_PA_PROV_SRV_LOCATION:
+               offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset,hf_krb_PA_DATA_value, dissect_krb5_PA_PROV_SRV_LOCATION);
+               break;
        case KRB5_PA_ENC_TIMESTAMP:
                offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset,hf_krb_PA_DATA_value, dissect_krb5_PA_ENC_TIMESTAMP);
                break;
@@ -2022,6 +2371,99 @@ dissect_krb5_EncAPRepPart(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, i
 
 
 
+static guint32 lr_type;
+static const value_string krb5_lr_types[] = {
+    { 0              , "No information available" },
+    { 1              , "Time of last initial TGT request" },
+    { 2              , "Time of last initial request" },
+    { 3              , "Time of issue of latest TGT ticket" },
+    { 4              , "Time of last renewal" },
+    { 5              , "Time of last request" },
+    { 6              , "Time when password will expire" },
+    { 7              , "Time when account will expire" },
+    { 0, NULL }
+};
+static int
+dissect_krb5_lr_type(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_lr_type, &lr_type);
+
+       return offset;
+}
+static int
+dissect_krb5_lr_value(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_lr_time);
+
+       return offset;
+}
+
+static ber_sequence LastReq_sequence[] = {
+       { BER_CLASS_CON, 0, 0,
+               dissect_krb5_lr_type },
+       { BER_CLASS_CON, 1, 0,
+               dissect_krb5_lr_value },
+       { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_LastReq(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, LastReq_sequence, hf_krb_LastReq, ett_krb_LastReq);
+
+       return offset;
+}
+static ber_sequence LastReq_sequence_of[1] = {
+  { BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_krb5_LastReq },
+};
+static int
+dissect_krb5_LastReq_sequence_of(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       offset=dissect_ber_sequence_of(FALSE, pinfo, tree, tvb, offset, LastReq_sequence_of, hf_krb_LastReqs, ett_krb_LastReqs);
+
+       return offset;
+}
+
+static int 
+dissect_krb5_key_expiration(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_key_expire);
+       return offset;
+}
+
+static ber_sequence EncKDCRepPart_sequence[] = {
+       { BER_CLASS_CON, 0, 0,
+               dissect_krb5_key },
+       { BER_CLASS_CON, 1, 0,
+               dissect_krb5_LastReq_sequence_of },
+       { BER_CLASS_CON, 2, 0,
+               dissect_krb5_nonce },
+       { BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL,
+               dissect_krb5_key_expiration },
+       { BER_CLASS_CON, 4, 0,
+               dissect_krb5_TicketFlags },
+       { BER_CLASS_CON, 5, 0,
+               dissect_krb5_authtime },
+       { BER_CLASS_CON, 6, BER_FLAGS_OPTIONAL,
+               dissect_krb5_starttime },
+       { BER_CLASS_CON, 7, 0,
+               dissect_krb5_endtime },
+       { BER_CLASS_CON, 8, BER_FLAGS_OPTIONAL,
+               dissect_krb5_renew_till },
+       { BER_CLASS_CON, 9, 0, 
+               dissect_krb5_realm },
+       { BER_CLASS_CON, 10, 0,
+               dissect_krb5_sname },
+       { BER_CLASS_CON, 11, BER_FLAGS_OPTIONAL,
+               dissect_krb5_HostAddresses },
+       { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_EncKDCRepPart(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, EncKDCRepPart_sequence, hf_krb_EncKDCRepPart, ett_krb_EncKDCRepPart);
+
+       return offset;
+}
 
 
 static int
@@ -2157,6 +2599,76 @@ dissect_krb5_PRIV(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offse
 }
 
 
+static int
+dissect_krb5_SAFE_BODY_user_data(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       tvbuff_t *new_tvb;
+       offset=dissect_ber_octet_string(FALSE, pinfo, tree, tvb, offset, hf_krb_SAFE_BODY_user_data, &new_tvb);
+       call_kerberos_callbacks(pinfo, tree, new_tvb, KRB_CBTAG_SAFE_USER_DATA);
+       return offset;
+}
+static int 
+dissect_krb5_SAFE_BODY_timestamp(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_SAFE_BODY_timestamp);
+       return offset;
+}
+
+static int
+dissect_krb5_SAFE_BODY_usec(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_SAFE_BODY_usec, NULL);
+       return offset;
+}
+
+static ber_sequence SAFE_BODY_sequence[] = {
+       { BER_CLASS_CON, 0, 0, 
+               dissect_krb5_SAFE_BODY_user_data },
+       { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, 
+               dissect_krb5_SAFE_BODY_timestamp },
+       { BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL, 
+               dissect_krb5_SAFE_BODY_usec },
+       { BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL,
+               dissect_krb5_seq_number },
+       /*XXX this one is OPTIONAL in packetcable?  but mandatory in kerberos */
+       { BER_CLASS_CON, 4, BER_FLAGS_OPTIONAL,
+               dissect_krb5_s_address },
+       { BER_CLASS_CON, 5, BER_FLAGS_OPTIONAL,
+               dissect_krb5_HostAddresses },
+       { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_SAFE_BODY(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+
+       offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, SAFE_BODY_sequence, -1, -1);
+
+       return offset;
+}
+
+
+
+static ber_sequence SAFE_sequence[] = {
+       { BER_CLASS_CON, 0, 0, 
+               dissect_krb5_pvno },
+       { BER_CLASS_CON, 1, 0, 
+               dissect_krb5_msg_type },
+       { BER_CLASS_CON, 2, 0, 
+               dissect_krb5_SAFE_BODY },
+       { BER_CLASS_CON, 3, 0, 
+               dissect_krb5_Checksum },
+       { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_SAFE(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+
+       offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, SAFE_sequence, -1, -1);
+
+       return offset;
+}
+
+
 /*
  * KDC-REQ-BODY ::=   SEQUENCE {
  *           kdc-options[0]       KDCOptions,
@@ -2189,7 +2701,12 @@ static ber_sequence KDC_REQ_BODY_sequence[] = {
                dissect_krb5_sname },
        { BER_CLASS_CON, 4, BER_FLAGS_OPTIONAL,
                dissect_krb5_from },
-       { BER_CLASS_CON, 5, 0,
+               /* this field is not optional in the kerberos spec, 
+                * however, in the packetcable spec it is optional.
+                * make it optional here since normal kerberos will
+                * still decode the pdu correctly.
+                */
+       { BER_CLASS_CON, 5, BER_FLAGS_OPTIONAL,
                dissect_krb5_till },
        { BER_CLASS_CON, 6, BER_FLAGS_OPTIONAL,
                dissect_krb5_rtime },
@@ -2548,19 +3065,77 @@ dissect_krb5_AP_REP(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int off
 
 
 
+static guint32 KDC_REP_etype;
+static int 
+dissect_krb5_KDC_REP_etype(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_etype, &KDC_REP_etype);
+       if(tree){
+               proto_item_append_text(tree, " %s", 
+                       val_to_str(KDC_REP_etype, krb5_encryption_types,
+                       "%#x"));
+       }
+       return offset;
+}
+
+#ifdef HAVE_KERBEROS
+static int
+dissect_krb5_decrypt_KDC_REP_data (packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+       guint8 *plaintext=NULL;
+       int length;
+
+       length=tvb_length_remaining(tvb, offset);
+
+       /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
+        * 7.5.1
+        * ASREP/TGSREP encryptedparts are encrypted with usage 
+        * == 3 or
+        * == 8 or
+         * == 9
+        */
+       if(!plaintext){
+               plaintext=decrypt_krb5_data(pinfo, 3, length, tvb_get_ptr(tvb, offset, length), KDC_REP_etype);
+       }
+       if(!plaintext){
+               plaintext=decrypt_krb5_data(pinfo, 8, length, tvb_get_ptr(tvb, offset, length), KDC_REP_etype);
+       }
+       if(!plaintext){
+               plaintext=decrypt_krb5_data(pinfo, 9, length, tvb_get_ptr(tvb, offset, length), KDC_REP_etype);
+       }
+
+       if(plaintext){
+               tvbuff_t *next_tvb;
+               next_tvb = tvb_new_real_data (plaintext,
+                                          length,
+                                          length);
+               tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+            
+               /* Add the decrypted data to the data source list. */
+               add_new_data_source(pinfo, next_tvb, "Decrypted Krb5");
+            
+
+               offset=dissect_ber_choice(pinfo, tree, next_tvb, 0, kerberos_applications_choice, -1, -1);
 
+       }
+       return offset;
+}
+#endif
 
 
 static int
 dissect_krb5_encrypted_KDC_REP_data(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
 {
-       offset=dissect_ber_octet_string(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_KDC_REP_data, NULL);
+#ifdef HAVE_KERBEROS
+       offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_KDC_REP_data, dissect_krb5_decrypt_KDC_REP_data);
+#else
+       offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_KDC_REP_data, NULL);
+#endif
        return offset;
-/*qqq*/
 }
 static ber_sequence encrypted_KDC_REP_sequence[] = {
        { BER_CLASS_CON, 0, 0, 
-               dissect_krb5_etype },
+               dissect_krb5_KDC_REP_etype },
        { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL,
                dissect_krb5_kvno },
        { BER_CLASS_CON, 2, 0,
@@ -2708,7 +3283,8 @@ 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);
+                                       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);
@@ -2717,9 +3293,9 @@ static guint get_krb_pdu_len(tvbuff_t *tvb, int offset);
 
 
 gint
-dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int do_col_info)
+dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int do_col_info, kerberos_callbacks *cb)
 {
-    return (dissect_kerberos_common(tvb, pinfo, tree, do_col_info, FALSE));
+    return (dissect_kerberos_common(tvb, pinfo, tree, do_col_info, FALSE, cb));
 }
 
 static void
@@ -2728,7 +3304,7 @@ 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);
+    (void)dissect_kerberos_common(tvb, pinfo, tree, TRUE, FALSE, NULL);
 }
 
 static gint
@@ -2752,7 +3328,7 @@ 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) {
+    if (dissect_kerberos_common(tvb, pinfo, tree, TRUE, TRUE, NULL) < 0) {
        /*
         * The dissector failed to recognize this as a valid
         * Kerberos message.  Mark it as a continuation packet.
@@ -2797,16 +3373,19 @@ show_krb_recordmark(proto_tree *tree, tvbuff_t *tvb, gint start, guint32 krb_rm)
 
 static gint
 dissect_kerberos_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
-    int dci, gboolean have_rm)
+    int dci, gboolean have_rm, kerberos_callbacks *cb)
 {
     int offset = 0;
     proto_tree *kerberos_tree = NULL;
     proto_item *item = NULL;
+    void *saved_private_data;
 
     /* TCP record mark and length */
     guint32 krb_rm = 0;
     gint krb_reclen = 0;
 
+    saved_private_data=pinfo->private_data;
+    pinfo->private_data=cb;
     do_col_info=dci;
 
     if (tree) {
@@ -2821,14 +3400,17 @@ dissect_kerberos_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
         * What is a reasonable size limit?
         */
        if (krb_reclen > 10 * 1024 * 1024) {
+           pinfo->private_data=saved_private_data;
            return (-1);
        }
        show_krb_recordmark(kerberos_tree, tvb, offset, krb_rm);
        offset += 4;
     }
 
-
     offset=dissect_ber_choice(pinfo, kerberos_tree, tvb, offset, kerberos_applications_choice, -1, -1);
+
+    proto_item_set_len(item, offset);
+    pinfo->private_data=saved_private_data;
     return offset;
 }
 
@@ -2868,7 +3450,7 @@ proto_register_kerberos(void)
            "Data", "kerberos.IF_RELEVANT.value", FT_BYTES, BASE_HEX,
            NULL, 0, "IF_RELEVANT Data", HFILL }},
        { &hf_krb_etype, {
-           "Encryption type", "kerberos.etype", FT_UINT32, BASE_DEC,
+           "Encryption type", "kerberos.etype", FT_INT32, BASE_DEC,
            VALS(krb5_encryption_types), 0, "Encryption Type", HFILL }},
        { &hf_krb_addr_type, {
            "Addr-type", "kerberos.addr_type", FT_UINT32, BASE_DEC,
@@ -2877,23 +3459,44 @@ proto_register_kerberos(void)
            "Type", "kerberos.pac.signature.type", FT_INT32, BASE_DEC,
            NULL, 0, "PAC Signature Type", HFILL }},
        { &hf_krb_name_type, {
-           "Name-type", "kerberos.name_type", FT_UINT32, BASE_DEC,
+           "Name-type", "kerberos.name_type", FT_INT32, BASE_DEC,
            VALS(krb5_princ_types), 0, "Type of principal name", HFILL }},
+       { &hf_krb_lr_type, {
+           "Lr-type", "kerberos.lr_type", FT_UINT32, BASE_DEC,
+           VALS(krb5_lr_types), 0, "Type of lastreq value", HFILL }},
        { &hf_krb_address_ip, {
            "IP Address", "kerberos.addr_ip", FT_IPv4, BASE_NONE,
            NULL, 0, "IP Address", HFILL }},
        { &hf_krb_address_netbios, {
            "NetBIOS Address", "kerberos.addr_nb", FT_STRING, BASE_NONE,
            NULL, 0, "NetBIOS Address and type", HFILL }},
+       { &hf_krb_contentinfo_contenttype, {
+           "ContentType", "kerberos.contenttype", FT_STRING, BASE_NONE,
+           NULL, 0, "ContentInfo ContentType field", HFILL }},
        { &hf_krb_authtime, {
            "Authtime", "kerberos.authtime", FT_STRING, BASE_NONE,
            NULL, 0, "Time of initial authentication", HFILL }},
+       { &hf_krb_SAFE_BODY_timestamp, {
+           "Timestamp", "kerberos.SAFE_BODY.timestamp", FT_STRING, BASE_NONE,
+           NULL, 0, "Timestamp of this SAFE_BODY", HFILL }},
+       { &hf_krb_patimestamp, {
+           "patimestamp", "kerberos.patimestamp", FT_STRING, BASE_NONE,
+           NULL, 0, "Time of client", HFILL }},
+       { &hf_krb_pausec, {
+           "pausec", "kerberos.pausec", FT_UINT32, BASE_DEC,
+           NULL, 0, "Microsecond component of client time", HFILL }},
+       { &hf_krb_lr_time, {
+           "Lr-time", "kerberos.lr_time", FT_STRING, BASE_NONE,
+           NULL, 0, "Time of LR-entry", HFILL }},
        { &hf_krb_starttime, {
            "Start time", "kerberos.starttime", FT_STRING, BASE_NONE,
            NULL, 0, "The time after which the ticket is valid", HFILL }},
        { &hf_krb_endtime, {
            "End time", "kerberos.endtime", FT_STRING, BASE_NONE,
            NULL, 0, "The time after which the ticket has expired", HFILL }},
+       { &hf_krb_key_expire, {
+           "Key Expiration", "kerberos.key_expiration", FT_STRING, BASE_NONE,
+           NULL, 0, "The time after which the key will expire", HFILL }},
        { &hf_krb_renew_till, {
            "Renew-till", "kerberos.renenw_till", FT_STRING, BASE_NONE,
            NULL, 0, "The maximum time we can renew the ticket until", HFILL }},
@@ -2906,6 +3509,9 @@ proto_register_kerberos(void)
        { &hf_krb_cusec, {
            "cusec", "kerberos.cusec", FT_UINT32, BASE_DEC,
            NULL, 0, "micro second component of client time", HFILL }},
+       { &hf_krb_SAFE_BODY_usec, {
+           "usec", "kerberos.SAFE_BODY.usec", FT_UINT32, BASE_DEC,
+           NULL, 0, "micro second component of SAFE_BODY time", HFILL }},
        { &hf_krb_stime, {
            "stime", "kerberos.stime", FT_STRING, BASE_NONE,
            NULL, 0, "Current Time on the server host", HFILL }},
@@ -2924,6 +3530,9 @@ proto_register_kerberos(void)
        { &hf_krb_name_string, {
            "Name", "kerberos.name_string", FT_STRING, BASE_NONE,
            NULL, 0, "String component that is part of a PrincipalName", HFILL }},
+       { &hf_krb_provsrv_location, {
+           "PROVSRV Location", "kerberos.provsrv_location", FT_STRING, BASE_NONE,
+           NULL, 0, "PacketCable PROV SRV Location", HFILL }},
        { &hf_krb_e_text, {
            "e-text", "kerberos.e_text", FT_STRING, BASE_NONE,
            NULL, 0, "Additional (human readable) error description", HFILL }},
@@ -3023,6 +3632,9 @@ proto_register_kerberos(void)
        { &hf_krb_KDCOptions_renewable, {
            "Renewable", "kerberos.kdcoptions.renewable", FT_BOOLEAN, 32,
            TFS(&krb5_kdcoptions_renewable), 0x00800000, "Whether this ticket is renewable or not", HFILL }},
+       { &hf_krb_KDCOptions_canonicalize, {
+           "Canonicalize", "kerberos.kdcoptions.canonicalize", FT_BOOLEAN, 32,
+           TFS(&krb5_kdcoptions_canonicalize), 0x00010000, "Do we want the KDC to canonicalize the principal or not", HFILL }},
        { &hf_krb_KDCOptions_opt_hardware_auth, {
            "Opt HW Auth", "kerberos.kdcoptions.opt_hardware_auth", FT_BOOLEAN, 32,
            NULL, 0x00100000, "Opt HW Auth flag", HFILL }},
@@ -3049,7 +3661,7 @@ proto_register_kerberos(void)
            NULL, 0, "Version Number for the encryption Key", HFILL }},
        { &hf_krb_checksum_type, {
            "Type", "kerberos.checksum.type", FT_UINT32, BASE_DEC,
-           NULL, 0, "Type of checksum", HFILL }},
+           VALS(krb5_checksum_types), 0, "Type of checksum", HFILL }},
        { &hf_krb_authenticator_vno, {
            "Authenticator vno", "kerberos.authenticator_vno", FT_UINT32, BASE_DEC,
            NULL, 0, "Version Number for the Authenticator", HFILL }},
@@ -3095,6 +3707,9 @@ proto_register_kerberos(void)
        { &hf_krb_etype_info_salt, {
            "Salt", "kerberos.etype_info.salt", FT_BYTES, BASE_HEX,
            NULL, 0, "Salt", HFILL }},
+       { &hf_krb_SAFE_BODY_user_data, {
+           "User Data", "kerberos.SAFE_BODY.user_data", FT_BYTES, BASE_HEX,
+           NULL, 0, "SAFE BODY userdata field", HFILL }},
        { &hf_krb_pac_signature_signature, {
            "Signature", "kerberos.pac.signature.signature", FT_BYTES, BASE_HEX,
            NULL, 0, "A PAC signature blob", HFILL }},
@@ -3110,6 +3725,12 @@ proto_register_kerberos(void)
        { &hf_krb_HostAddress, {
            "HostAddress", "kerberos.hostaddress", FT_NONE, BASE_DEC,
            NULL, 0, "This is a Kerberos HostAddress sequence", HFILL }},
+       { &hf_krb_s_address, {
+           "S-Address", "kerberos.s_address", FT_NONE, BASE_DEC,
+           NULL, 0, "This is the Senders address", HFILL }},
+       { &hf_krb_signedAuthPack, {
+           "signedAuthPack", "kerberos.signedAuthPack", FT_NONE, BASE_DEC,
+           NULL, 0, "This is a Kerberos ContentInfo sequence", HFILL }},
        { &hf_krb_key, {
            "key", "kerberos.key", FT_NONE, BASE_DEC,
            NULL, 0, "This is a Kerberos EncryptionKey sequence", HFILL }},
@@ -3128,6 +3749,12 @@ proto_register_kerberos(void)
        { &hf_krb_EncAPRepPart, {
            "EncAPRepPart", "kerberos.EncAPRepPart", FT_NONE, BASE_DEC,
            NULL, 0, "This is a decrypted Kerberos EncAPRepPart sequence", HFILL }},
+       { &hf_krb_EncKDCRepPart, {
+           "EncKDCRepPart", "kerberos.EncKDCRepPart", FT_NONE, BASE_DEC,
+           NULL, 0, "This is a decrypted Kerberos EncKDCRepPart sequence", HFILL }},
+       { &hf_krb_LastReq, {
+           "LastReq", "kerberos.LastReq", FT_NONE, BASE_DEC,
+           NULL, 0, "This is a LastReq sequence", HFILL }},
        { &hf_krb_Authenticator, {
            "Authenticator", "kerberos.Authenticator", FT_NONE, BASE_DEC,
            NULL, 0, "This is a decrypted Kerberos Authenticator sequence", HFILL }},
@@ -3143,6 +3770,9 @@ proto_register_kerberos(void)
        { &hf_krb_etypes, {
            "Encryption Types", "kerberos.etypes", FT_NONE, BASE_DEC,
            NULL, 0, "This is a list of Kerberos encryption types", HFILL }},
+       { &hf_krb_LastReqs, {
+           "LastReqs", "kerberos.LastReqs", FT_NONE, BASE_DEC,
+           NULL, 0, "This is a list of LastReq structures", HFILL }},
        { &hf_krb_sname, {
            "Server Name", "kerberos.sname", FT_NONE, BASE_DEC,
            NULL, 0, "This is the name part server's identity", HFILL }},
@@ -3207,8 +3837,10 @@ proto_register_kerberos(void)
        &ett_krb_AP_REP_enc,
         &ett_krb_padata,
         &ett_krb_etypes,
+        &ett_krb_LastReqs,
         &ett_krb_IF_RELEVANT,
        &ett_krb_PA_DATA_tree,
+        &ett_krb_s_address,
         &ett_krb_HostAddress,
         &ett_krb_HostAddresses,
        &ett_krb_authenticator_enc,
@@ -3223,6 +3855,8 @@ proto_register_kerberos(void)
         &ett_krb_PRIV_enc,
         &ett_krb_EncTicketPart,
         &ett_krb_EncAPRepPart,
+        &ett_krb_EncKDCRepPart,
+        &ett_krb_LastReq,
         &ett_krb_Authenticator,
         &ett_krb_Checksum,
         &ett_krb_key,
@@ -3235,6 +3869,7 @@ proto_register_kerberos(void)
        &ett_krb_PAC_SERVER_CHECKSUM,
        &ett_krb_PAC_PRIVSVR_CHECKSUM,
        &ett_krb_PAC_CLIENT_INFO_TYPE,
+       &ett_krb_signedAuthPack,
     };
     module_t *krb_module;
 
@@ -3262,6 +3897,32 @@ proto_register_kerberos(void)
 #endif
 }
 
+static int wrap_dissect_gss_kerb(tvbuff_t *tvb, int offset, packet_info *pinfo,
+                                proto_tree *tree, guint8 *drep _U_)
+{
+       tvbuff_t *auth_tvb;
+
+       auth_tvb = tvb_new_subset(
+               tvb, offset, tvb_length_remaining(tvb, offset),
+               tvb_length_remaining(tvb, offset));
+
+       dissect_kerberos_main(auth_tvb, pinfo, tree, FALSE, NULL);
+
+       return tvb_length_remaining(tvb, offset);
+}
+
+
+static dcerpc_auth_subdissector_fns gss_kerb_auth_fns = {
+       wrap_dissect_gss_kerb,                  /* Bind */
+       wrap_dissect_gss_kerb,                  /* Bind ACK */
+       NULL,                                   /* AUTH3 */
+       wrap_dissect_gssapi_verf,               /* Request verifier */
+       wrap_dissect_gssapi_verf,               /* Response verifier */
+       NULL,                                   /* Request data */
+       NULL                                    /* Response data */
+};
+
+
 void
 proto_reg_handoff_kerberos(void)
 {
@@ -3275,6 +3936,10 @@ proto_reg_handoff_kerberos(void)
     dissector_add("udp.port", UDP_PORT_KERBEROS, kerberos_handle_udp);
     dissector_add("tcp.port", TCP_PORT_KERBEROS, kerberos_handle_tcp);
 
+    register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
+                                     DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
+                                     &gss_kerb_auth_fns);
+
 }
 
 /*