Include files from the "epan" directory and subdirectories thereof with
[obnox/wireshark/wip.git] / packet-kerberos.c
1 /* packet-kerberos.c
2  * Routines for Kerberos
3  * Wes Hardaker (c) 2000
4  * wjhardaker@ucdavis.edu
5  *
6  * $Id: packet-kerberos.c,v 1.20 2002/01/21 07:36:36 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  * 
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <ctype.h>
34
35 #ifdef HAVE_SYS_TYPES_H
36 # include <sys/types.h>
37 #endif
38
39 #include <glib.h>
40
41 #include <epan/packet.h>
42
43 #include <epan/strutil.h>
44
45 #include "asn1.h"
46
47 #define UDP_PORT_KERBEROS               88
48 #define TCP_PORT_KERBEROS               88
49
50 static gint proto_kerberos = -1;
51
52 static gint ett_kerberos = -1;
53 static gint ett_preauth = -1;
54 static gint ett_addresses = -1;
55 static gint ett_request = -1;
56 static gint ett_princ = -1;
57 static gint ett_ticket = -1;
58 static gint ett_encrypted = -1;
59 static gint ett_etype = -1;
60 static gint ett_additional_tickets = -1;
61
62 #define KRB5_MSG_AS_REQ   10    /* AS-REQ type */
63 #define KRB5_MSG_AS_REP   11    /* AS-REP type */
64 #define KRB5_MSG_TGS_REQ  12    /* TGS-REQ type */
65 #define KRB5_MSG_TGS_REP  13    /* TGS-REP type */
66 #define KRB5_MSG_AP_REQ   14    /* AP-REQ type */
67 #define KRB5_MSG_AP_REP   15    /* AP-REP type */
68
69 #define KRB5_MSG_SAFE     20    /* KRB-SAFE type */
70 #define KRB5_MSG_PRIV     21    /* KRB-PRIV type */
71 #define KRB5_MSG_CRED     22    /* KRB-CRED type */
72 #define KRB5_MSG_ERROR    30    /* KRB-ERROR type */
73
74 /* Type tags within KDC-REQ */
75 #define KRB5_KDC_REQ_PVNO     1
76 #define KRB5_KDC_REQ_MSG_TYPE 2
77 #define KRB5_KDC_REQ_PADATA   3
78 #define KRB5_KDC_REQ_REQBODY  4
79
80 /* Type tags within KDC-REP */
81 #define KRB5_KDC_REP_PVNO     0
82 #define KRB5_KDC_REP_MSG_TYPE 1
83 #define KRB5_KDC_REP_PADATA   2
84 #define KRB5_KDC_REP_CREALM   3
85 #define KRB5_KDC_REP_CNAME    4
86 #define KRB5_KDC_REP_TICKET   5
87 #define KRB5_KDC_REP_ENC_PART 6
88
89 /* Type tags within KDC-REQ-BODY */
90 #define KRB5_BODY_KDC_OPTIONS            0
91 #define KRB5_BODY_CNAME                  1
92 #define KRB5_BODY_REALM                  2
93 #define KRB5_BODY_SNAME                  3
94 #define KRB5_BODY_FROM                   4
95 #define KRB5_BODY_TILL                   5
96 #define KRB5_BODY_RTIME                  6
97 #define KRB5_BODY_NONCE                  7
98 #define KRB5_BODY_ENCTYPE                8
99 #define KRB5_BODY_ADDRESSES              9
100 #define KRB5_BODY_ENC_AUTHORIZATION_DATA 10
101 #define KRB5_BODY_ADDITIONAL_TICKETS     11
102
103 /* Type tags within KRB-ERROR */
104 #define KRB5_ERROR_PVNO       0
105 #define KRB5_ERROR_MSG_TYPE   1
106 #define KRB5_ERROR_CTIME      2
107 #define KRB5_ERROR_CUSEC      3
108 #define KRB5_ERROR_STIME      4
109 #define KRB5_ERROR_SUSEC      5
110 #define KRB5_ERROR_ERROR_CODE 6
111 #define KRB5_ERROR_CREALM     7
112 #define KRB5_ERROR_CNAME      8
113 #define KRB5_ERROR_REALM      9
114 #define KRB5_ERROR_SNAME      10
115 #define KRB5_ERROR_ETEXT      11
116 #define KRB5_ERROR_EDATA      12
117
118 /* address type constants */
119 #define KRB5_ADDR_IPv4       0x02
120 #define KRB5_ADDR_CHAOS      0x05
121 #define KRB5_ADDR_XEROX      0x06
122 #define KRB5_ADDR_ISO        0x07
123 #define KRB5_ADDR_DECNET     0x0c
124 #define KRB5_ADDR_APPLETALK  0x10
125
126 /* encryption type constants */
127 #define KRB5_ENCTYPE_NULL                0
128 #define KRB5_ENCTYPE_DES_CBC_CRC         1
129 #define KRB5_ENCTYPE_DES_CBC_MD4         2
130 #define KRB5_ENCTYPE_DES_CBC_MD5         3
131 #define KRB5_ENCTYPE_DES_CBC_RAW         4
132 #define KRB5_ENCTYPE_DES3_CBC_SHA        5
133 #define KRB5_ENCTYPE_DES3_CBC_RAW        6
134 #define KRB5_ENCTYPE_DES_HMAC_SHA1       8
135 #define KRB5_ENCTYPE_DES3_CBC_SHA1          0x10 
136 #define KRB5_ENCTYPE_UNKNOWN                0x1ff
137 #define KRB5_ENCTYPE_LOCAL_DES3_HMAC_SHA1   0x7007
138
139 /* pre-authentication type constants */
140 #define KRB5_PA_TGS_REQ                1
141 #define KRB5_PA_ENC_TIMESTAMP          2
142 #define KRB5_PA_PW_SALT                3
143 #define KRB5_PA_ENC_ENCKEY             4
144 #define KRB5_PA_ENC_UNIX_TIME          5
145 #define KRB5_PA_ENC_SANDIA_SECURID     6
146 #define KRB5_PA_SESAME                 7
147 #define KRB5_PA_OSF_DCE                8
148 #define KRB5_PA_CYBERSAFE_SECUREID     9
149 #define KRB5_PA_AFS3_SALT              10
150 #define KRB5_PA_ENCTYPE_INFO             11
151 #define KRB5_PA_SAM_CHALLENGE          12
152 #define KRB5_PA_SAM_RESPONSE           13
153 #define KRB5_PA_DASS                   16
154
155 /* Type tags within Ticket */
156 #define KRB5_TKT_TKT_VNO  0
157 #define KRB5_TKT_REALM    1
158 #define KRB5_TKT_SNAME    2
159 #define KRB5_TKT_ENC_PART 3
160
161 /* Principal name-type */
162 #define KRB5_NT_UNKNOWN     0
163 #define KRB5_NT_PRINCIPAL   1
164 #define KRB5_NT_SRV_INST    2
165 #define KRB5_NT_SRV_HST     3
166 #define KRB5_NT_SRV_XHST    4
167 #define KRB5_NT_UID     5
168
169 /* error table constants */
170 /* I prefixed the krb5_err.et constant names with KRB5_ET_ for these */
171 #define KRB5_ET_KRB5KDC_ERR_NONE                         0
172 #define KRB5_ET_KRB5KDC_ERR_NAME_EXP                     1
173 #define KRB5_ET_KRB5KDC_ERR_SERVICE_EXP                  2
174 #define KRB5_ET_KRB5KDC_ERR_BAD_PVNO                     3
175 #define KRB5_ET_KRB5KDC_ERR_C_OLD_MAST_KVNO              4
176 #define KRB5_ET_KRB5KDC_ERR_S_OLD_MAST_KVNO              5
177 #define KRB5_ET_KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN          6
178 #define KRB5_ET_KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN          7
179 #define KRB5_ET_KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE         8
180 #define KRB5_ET_KRB5KDC_ERR_NULL_KEY                     9
181 #define KRB5_ET_KRB5KDC_ERR_CANNOT_POSTDATE              10
182 #define KRB5_ET_KRB5KDC_ERR_NEVER_VALID                  11
183 #define KRB5_ET_KRB5KDC_ERR_POLICY                       12
184 #define KRB5_ET_KRB5KDC_ERR_BADOPTION                    13
185 #define KRB5_ET_KRB5KDC_ERR_ETYPE_NOSUPP                 14
186 #define KRB5_ET_KRB5KDC_ERR_SUMTYPE_NOSUPP               15
187 #define KRB5_ET_KRB5KDC_ERR_PADATA_TYPE_NOSUPP           16
188 #define KRB5_ET_KRB5KDC_ERR_TRTYPE_NOSUPP                17
189 #define KRB5_ET_KRB5KDC_ERR_CLIENT_REVOKED               18
190 #define KRB5_ET_KRB5KDC_ERR_SERVICE_REVOKED              19
191 #define KRB5_ET_KRB5KDC_ERR_TGT_REVOKED                  20
192 #define KRB5_ET_KRB5KDC_ERR_CLIENT_NOTYET                21
193 #define KRB5_ET_KRB5KDC_ERR_SERVICE_NOTYET               22
194 #define KRB5_ET_KRB5KDC_ERR_KEY_EXP                      23
195 #define KRB5_ET_KRB5KDC_ERR_PREAUTH_FAILED               24
196 #define KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED             25
197 #define KRB5_ET_KRB5KDC_ERR_SERVER_NOMATCH               26
198 #define KRB5_ET_KRB5KRB_AP_ERR_BAD_INTEGRITY             31
199 #define KRB5_ET_KRB5KRB_AP_ERR_TKT_EXPIRED               32
200 #define KRB5_ET_KRB5KRB_AP_ERR_TKT_NYV                   33
201 #define KRB5_ET_KRB5KRB_AP_ERR_REPEAT                    34
202 #define KRB5_ET_KRB5KRB_AP_ERR_NOT_US                    35
203 #define KRB5_ET_KRB5KRB_AP_ERR_BADMATCH                  36
204 #define KRB5_ET_KRB5KRB_AP_ERR_SKEW                      37
205 #define KRB5_ET_KRB5KRB_AP_ERR_BADADDR                   38
206 #define KRB5_ET_KRB5KRB_AP_ERR_BADVERSION                39
207 #define KRB5_ET_KRB5KRB_AP_ERR_MSG_TYPE                  40
208 #define KRB5_ET_KRB5KRB_AP_ERR_MODIFIED                  41
209 #define KRB5_ET_KRB5KRB_AP_ERR_BADORDER                  42
210 #define KRB5_ET_KRB5KRB_AP_ERR_ILL_CR_TKT                43
211 #define KRB5_ET_KRB5KRB_AP_ERR_BADKEYVER                 44
212 #define KRB5_ET_KRB5KRB_AP_ERR_NOKEY                     45
213 #define KRB5_ET_KRB5KRB_AP_ERR_MUT_FAIL                  46
214 #define KRB5_ET_KRB5KRB_AP_ERR_BADDIRECTION              47
215 #define KRB5_ET_KRB5KRB_AP_ERR_METHOD                    48
216 #define KRB5_ET_KRB5KRB_AP_ERR_BADSEQ                    49
217 #define KRB5_ET_KRB5KRB_AP_ERR_INAPP_CKSUM               50
218 #define KRB5_ET_KRB5KRB_ERR_GENERIC                      60
219 #define KRB5_ET_KRB5KRB_ERR_FIELD_TOOLONG                61
220
221 static const value_string krb5_error_codes[] = {
222         { KRB5_ET_KRB5KDC_ERR_NONE, "KRB5KDC_ERR_NONE" },
223         { KRB5_ET_KRB5KDC_ERR_NAME_EXP, "KRB5KDC_ERR_NAME_EXP" },
224         { KRB5_ET_KRB5KDC_ERR_SERVICE_EXP, "KRB5KDC_ERR_SERVICE_EXP" },
225         { KRB5_ET_KRB5KDC_ERR_BAD_PVNO, "KRB5KDC_ERR_BAD_PVNO" },
226         { KRB5_ET_KRB5KDC_ERR_C_OLD_MAST_KVNO, "KRB5KDC_ERR_C_OLD_MAST_KVNO" },
227         { KRB5_ET_KRB5KDC_ERR_S_OLD_MAST_KVNO, "KRB5KDC_ERR_S_OLD_MAST_KVNO" },
228         { KRB5_ET_KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, "KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN" },
229         { KRB5_ET_KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, "KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN" },
230         { KRB5_ET_KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE, "KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE" },
231         { KRB5_ET_KRB5KDC_ERR_NULL_KEY, "KRB5KDC_ERR_NULL_KEY" },
232         { KRB5_ET_KRB5KDC_ERR_CANNOT_POSTDATE, "KRB5KDC_ERR_CANNOT_POSTDATE" },
233         { KRB5_ET_KRB5KDC_ERR_NEVER_VALID, "KRB5KDC_ERR_NEVER_VALID" },
234         { KRB5_ET_KRB5KDC_ERR_POLICY, "KRB5KDC_ERR_POLICY" },
235         { KRB5_ET_KRB5KDC_ERR_BADOPTION, "KRB5KDC_ERR_BADOPTION" },
236         { KRB5_ET_KRB5KDC_ERR_ETYPE_NOSUPP, "KRB5KDC_ERR_ETYPE_NOSUPP" },
237         { KRB5_ET_KRB5KDC_ERR_SUMTYPE_NOSUPP, "KRB5KDC_ERR_SUMTYPE_NOSUPP" },
238         { KRB5_ET_KRB5KDC_ERR_PADATA_TYPE_NOSUPP, "KRB5KDC_ERR_PADATA_TYPE_NOSUPP" },
239         { KRB5_ET_KRB5KDC_ERR_TRTYPE_NOSUPP, "KRB5KDC_ERR_TRTYPE_NOSUPP" },
240         { KRB5_ET_KRB5KDC_ERR_CLIENT_REVOKED, "KRB5KDC_ERR_CLIENT_REVOKED" },
241         { KRB5_ET_KRB5KDC_ERR_SERVICE_REVOKED, "KRB5KDC_ERR_SERVICE_REVOKED" },
242         { KRB5_ET_KRB5KDC_ERR_TGT_REVOKED, "KRB5KDC_ERR_TGT_REVOKED" },
243         { KRB5_ET_KRB5KDC_ERR_CLIENT_NOTYET, "KRB5KDC_ERR_CLIENT_NOTYET" },
244         { KRB5_ET_KRB5KDC_ERR_SERVICE_NOTYET, "KRB5KDC_ERR_SERVICE_NOTYET" },
245         { KRB5_ET_KRB5KDC_ERR_KEY_EXP, "KRB5KDC_ERR_KEY_EXP" },
246         { KRB5_ET_KRB5KDC_ERR_PREAUTH_FAILED, "KRB5KDC_ERR_PREAUTH_FAILED" },
247         { KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED, "KRB5KDC_ERR_PREAUTH_REQUIRED" },
248         { KRB5_ET_KRB5KDC_ERR_SERVER_NOMATCH, "KRB5KDC_ERR_SERVER_NOMATCH" },
249         { KRB5_ET_KRB5KRB_AP_ERR_BAD_INTEGRITY, "KRB5KRB_AP_ERR_BAD_INTEGRITY" },
250         { KRB5_ET_KRB5KRB_AP_ERR_TKT_EXPIRED, "KRB5KRB_AP_ERR_TKT_EXPIRED" },
251         { KRB5_ET_KRB5KRB_AP_ERR_TKT_NYV, "KRB5KRB_AP_ERR_TKT_NYV" },
252         { KRB5_ET_KRB5KRB_AP_ERR_REPEAT, "KRB5KRB_AP_ERR_REPEAT" },
253         { KRB5_ET_KRB5KRB_AP_ERR_NOT_US, "KRB5KRB_AP_ERR_NOT_US" },
254         { KRB5_ET_KRB5KRB_AP_ERR_BADMATCH, "KRB5KRB_AP_ERR_BADMATCH" },
255         { KRB5_ET_KRB5KRB_AP_ERR_SKEW, "KRB5KRB_AP_ERR_SKEW" },
256         { KRB5_ET_KRB5KRB_AP_ERR_BADADDR, "KRB5KRB_AP_ERR_BADADDR" },
257         { KRB5_ET_KRB5KRB_AP_ERR_BADVERSION, "KRB5KRB_AP_ERR_BADVERSION" },
258         { KRB5_ET_KRB5KRB_AP_ERR_MSG_TYPE, "KRB5KRB_AP_ERR_MSG_TYPE" },
259         { KRB5_ET_KRB5KRB_AP_ERR_MODIFIED, "KRB5KRB_AP_ERR_MODIFIED" },
260         { KRB5_ET_KRB5KRB_AP_ERR_BADORDER, "KRB5KRB_AP_ERR_BADORDER" },
261         { KRB5_ET_KRB5KRB_AP_ERR_ILL_CR_TKT, "KRB5KRB_AP_ERR_ILL_CR_TKT" },
262         { KRB5_ET_KRB5KRB_AP_ERR_BADKEYVER, "KRB5KRB_AP_ERR_BADKEYVER" },
263         { KRB5_ET_KRB5KRB_AP_ERR_NOKEY, "KRB5KRB_AP_ERR_NOKEY" },
264         { KRB5_ET_KRB5KRB_AP_ERR_MUT_FAIL, "KRB5KRB_AP_ERR_MUT_FAIL" },
265         { KRB5_ET_KRB5KRB_AP_ERR_BADDIRECTION, "KRB5KRB_AP_ERR_BADDIRECTION" },
266         { KRB5_ET_KRB5KRB_AP_ERR_METHOD, "KRB5KRB_AP_ERR_METHOD" },
267         { KRB5_ET_KRB5KRB_AP_ERR_BADSEQ, "KRB5KRB_AP_ERR_BADSEQ" },
268         { KRB5_ET_KRB5KRB_AP_ERR_INAPP_CKSUM, "KRB5KRB_AP_ERR_INAPP_CKSUM" },
269         { KRB5_ET_KRB5KRB_ERR_GENERIC, "KRB5KRB_ERR_GENERIC" },
270         { KRB5_ET_KRB5KRB_ERR_FIELD_TOOLONG, "KRB5KRB_ERR_FIELD_TOOLONG" },
271         { 0, NULL }
272 };
273
274
275 static const value_string krb5_princ_types[] = {
276     { KRB5_NT_UNKNOWN              , "Unknown" },
277     { KRB5_NT_PRINCIPAL            , "Principal" },
278     { KRB5_NT_SRV_INST             , "Service and Instance" },
279     { KRB5_NT_SRV_HST              , "Service and Host" },
280     { KRB5_NT_SRV_XHST             , "Service and Host Components" },
281     { KRB5_NT_UID                  , "Unique ID" },
282     { 0                            , NULL },
283 };
284
285 static const value_string krb5_preauthentication_types[] = {
286     { KRB5_PA_TGS_REQ              , "PA-TGS-REQ" },
287     { KRB5_PA_ENC_TIMESTAMP        , "PA-ENC-TIMESTAMP" },
288     { KRB5_PA_PW_SALT              , "PA-PW-SALT" },
289     { KRB5_PA_ENC_ENCKEY           , "PA-ENC-ENCKEY" },
290     { KRB5_PA_ENC_UNIX_TIME        , "PA-ENC-UNIX-TIME" },
291     { KRB5_PA_ENC_SANDIA_SECURID   , "PA-PW-SALT" },
292     { KRB5_PA_SESAME               , "PA-SESAME" },
293     { KRB5_PA_OSF_DCE              , "PA-OSF-DCE" },
294     { KRB5_PA_CYBERSAFE_SECUREID   , "PA-CYBERSAFE-SECURID" },
295     { KRB5_PA_AFS3_SALT            , "PA-AFS3-SALT" },
296     { KRB5_PA_ENCTYPE_INFO         , "PA-ENCTYPE-INFO" },
297     { KRB5_PA_SAM_CHALLENGE        , "PA-SAM-CHALLENGE" },
298     { KRB5_PA_SAM_RESPONSE         , "PA-SAM-RESPONSE" },
299     { KRB5_PA_DASS                 , "PA-DASS" },
300     { 0                            , NULL },
301 };
302
303 static const value_string krb5_encryption_types[] = {
304     { KRB5_ENCTYPE_NULL           , "NULL" },
305     { KRB5_ENCTYPE_DES_CBC_CRC    , "des-cbc-crc" },
306     { KRB5_ENCTYPE_DES_CBC_MD4    , "des-cbc-md4" },
307     { KRB5_ENCTYPE_DES_CBC_MD5    , "des-cbc-md5" },
308     { KRB5_ENCTYPE_DES_CBC_RAW    , "des-cbc-raw" },
309     { KRB5_ENCTYPE_DES3_CBC_SHA   , "des3-cbc-sha" },
310     { KRB5_ENCTYPE_DES3_CBC_RAW   , "des3-cbc-raw" },
311     { KRB5_ENCTYPE_DES_HMAC_SHA1  , "des-hmac-sha1" },
312     { KRB5_ENCTYPE_DES3_CBC_SHA1  , "des3-cbc-sha1" },
313     { KRB5_ENCTYPE_UNKNOWN        , "unknown" },
314     { KRB5_ENCTYPE_LOCAL_DES3_HMAC_SHA1    , "local-des3-hmac-sha1" },
315     { 0                            , NULL },
316 };
317
318 static const value_string krb5_address_types[] = {
319     { KRB5_ADDR_IPv4,           "IPv4"},
320     { KRB5_ADDR_CHAOS,          "CHAOS"},
321     { KRB5_ADDR_XEROX,          "XEROX"},
322     { KRB5_ADDR_ISO,            "ISO"},
323     { KRB5_ADDR_DECNET,         "DECNET"},
324     { KRB5_ADDR_APPLETALK,      "APPLETALK"},
325     { 0,                        NULL },
326 };
327
328 static const value_string krb5_msg_types[] = {
329         { KRB5_MSG_TGS_REQ,     "TGS-REQ" },
330         { KRB5_MSG_TGS_REP,     "TGS-REP" },
331         { KRB5_MSG_AS_REQ,      "AS-REQ" },
332         { KRB5_MSG_AS_REP,      "AS-REP" },
333         { KRB5_MSG_AP_REQ,      "AP-REQ" },
334         { KRB5_MSG_AP_REP,      "AP-REP" },
335         { KRB5_MSG_SAFE,        "KRB-SAFE" },
336         { KRB5_MSG_PRIV,        "KRB-PRIV" },
337         { KRB5_MSG_CRED,        "KRB-CRED" },
338         { KRB5_MSG_ERROR,       "KRB-ERROR" },
339         { 0,                    NULL },
340 };
341
342 static int dissect_PrincipalName(char *title, ASN1_SCK *asn1p,
343                                  packet_info *pinfo, proto_tree *tree,
344                                  int start_offset);
345 static int dissect_Ticket(char *title, ASN1_SCK *asn1p, packet_info *pinfo,
346                           proto_tree *tree, int start_offset);
347 static int dissect_EncryptedData(char *title, ASN1_SCK *asn1p,
348                                  packet_info *pinfo, proto_tree *tree,
349                                  int start_offset);
350 static int dissect_Addresses(char *title, ASN1_SCK *asn1p, packet_info *pinfo,
351                              proto_tree *tree, int start_offset);
352
353 static const char *
354 to_error_str(int ret) {
355     switch (ret) {
356
357         case ASN1_ERR_EOC_MISMATCH:
358             return("EOC mismatch");
359
360         case ASN1_ERR_WRONG_TYPE:
361             return("Wrong type for that item");
362
363         case ASN1_ERR_LENGTH_NOT_DEFINITE:
364             return("Length was indefinite");
365
366         case ASN1_ERR_LENGTH_MISMATCH:
367             return("Length mismatch");
368
369         case ASN1_ERR_WRONG_LENGTH_FOR_TYPE:
370             return("Wrong length for that item's type");
371
372     }
373     return("Unknown error");
374 }
375
376 static void
377 krb_proto_tree_add_time(proto_tree *tree, tvbuff_t *tvb, int offset,
378                         int str_len, char *name, guchar *str)
379 {
380     if (tree)
381         proto_tree_add_text(tree, tvb, offset, str_len,
382                             "%s: %.4s-%.2s-%.2s %.2s:%.2s:%.2s (%.1s)",
383                             name, str, str+4, str+6,
384                             str+8, str+10, str+12,
385                             str+14);
386 }
387
388
389 /*
390  * You must be kidding.  I'm going to actually use a macro to do something?
391  *   bad me.  Bad me.
392  */
393
394 #define KRB_HEAD_DECODE_OR_DIE(token) \
395    start = asn1p->offset; \
396    ret = asn1_header_decode (asn1p, &cls, &con, &tag, &def, &item_len); \
397    if (ret != ASN1_ERR_NOERROR) {\
398        if (check_col(pinfo->cinfo, COL_INFO)) \
399            col_add_fstr(pinfo->cinfo, COL_INFO, "ERROR: Problem at %s: %s", \
400                     token, to_error_str(ret)); \
401        return -1; \
402    } \
403    if (!def) {\
404        if (check_col(pinfo->cinfo, COL_INFO)) \
405            col_add_fstr(pinfo->cinfo, COL_INFO, "not definite: %s", token); \
406        fprintf(stderr,"not definite: %s\n", token); \
407        return -1; \
408    } \
409    offset += (asn1p->offset - start);
410
411 #define CHECK_APPLICATION_TYPE(expected_tag) \
412     (cls == ASN1_APL && con == ASN1_CON && tag == expected_tag)
413
414 #define DIE_IF_NOT_APPLICATION_TYPE(token, expected_tag) \
415     if (!CHECK_APPLICATION_TYPE(expected_tag)) \
416         DIE_WITH_BAD_TYPE(token, expected_tag);
417
418 #define CHECK_CONTEXT_TYPE(expected_tag) \
419     (cls == ASN1_CTX && con == ASN1_CON && tag == expected_tag)
420
421 #define DIE_IF_NOT_CONTEXT_TYPE(token, expected_tag) \
422     if (!CHECK_CONTEXT_TYPE(expected_tag)) \
423         DIE_WITH_BAD_TYPE(token, expected_tag);
424
425 #define DIE_WITH_BAD_TYPE(token, expected_tag) \
426     { \
427       if (check_col(pinfo->cinfo, COL_INFO)) \
428          col_add_fstr(pinfo->cinfo, COL_INFO, "ERROR: Problem at %s: %s (tag=%d exp=%d)", \
429                       token, to_error_str(ASN1_ERR_WRONG_TYPE), tag, expected_tag); \
430       return -1; \
431     }
432
433 #define KRB_DECODE_APPLICATION_TAGGED_HEAD_OR_DIE(token, expected_tag) \
434     KRB_HEAD_DECODE_OR_DIE(token); \
435     DIE_IF_NOT_APPLICATION_TYPE(token, expected_tag);
436
437 #define KRB_DECODE_CONTEXT_HEAD_OR_DIE(token, expected_tag) \
438     KRB_HEAD_DECODE_OR_DIE(token); \
439     DIE_IF_NOT_CONTEXT_TYPE(token, expected_tag);
440
441 #define KRB_SEQ_HEAD_DECODE_OR_DIE(token) \
442    ret = asn1_sequence_decode (asn1p, &item_len, &header_len); \
443    if (ret != ASN1_ERR_NOERROR) {\
444        if (check_col(pinfo->cinfo, COL_INFO)) \
445            col_add_fstr(pinfo->cinfo, COL_INFO, "ERROR: Problem at %s: %s", \
446                     token, to_error_str(ret)); \
447        return -1; \
448    } \
449    offset += header_len;
450
451 #define KRB_DECODE_OR_DIE(token, fn, val) \
452     ret = fn (asn1p, &val, &length); \
453     if (ret != ASN1_ERR_NOERROR) { \
454        if (check_col(pinfo->cinfo, COL_INFO)) \
455          col_add_fstr(pinfo->cinfo, COL_INFO, "ERROR: Problem at %s: %s", \
456                      token, to_error_str(ret)); \
457         return -1; \
458     } \
459
460 #define KRB_DECODE_UINT32_OR_DIE(token, val) \
461     KRB_DECODE_OR_DIE(token, asn1_uint32_decode, val);
462
463 #define KRB_DECODE_STRING_OR_DIE(token, expected_tag, val, val_len, item_len) \
464     ret = asn1_string_decode (asn1p, &val, &val_len, &item_len, expected_tag); \
465     if (ret != ASN1_ERR_NOERROR) { \
466        if (check_col(pinfo->cinfo, COL_INFO)) \
467          col_add_fstr(pinfo->cinfo, COL_INFO, "ERROR: Problem at %s: %s", \
468                      token, to_error_str(ret)); \
469         return -1; \
470     }
471
472 #define KRB_DECODE_OCTET_STRING_OR_DIE(token, val, val_len, item_len) \
473     KRB_DECODE_STRING_OR_DIE(token, ASN1_OTS, val, val_len, item_len)
474
475 #define KRB_DECODE_GENERAL_STRING_OR_DIE(token, val, val_len, item_len) \
476     KRB_DECODE_STRING_OR_DIE(token, ASN1_GENSTR, val, val_len, item_len)
477
478 #define KRB_DECODE_GENERAL_TIME_OR_DIE(token, val, val_len, item_len) \
479     KRB_DECODE_STRING_OR_DIE(token, ASN1_GENTIM, val, val_len, item_len)
480
481 /* dissect_type_value_pair decodes (roughly) this:
482
483     SEQUENCE  {
484                         INTEGER,
485                         OCTET STRING
486     }
487
488     which is all over the place in krb5 */
489
490 static void
491 dissect_type_value_pair(ASN1_SCK *asn1p, int *inoff,
492                         guint32 *type, int *type_len, int *type_off,
493                         guchar **val, int *val_len, int *val_off) {
494     int offset = *inoff;
495     guint cls, con, tag;
496     gboolean def;
497     int start;
498     guint tmp_len;
499     int ret;
500
501     /* SEQUENCE */
502     start = asn1p->offset;
503     asn1_header_decode (asn1p, &cls, &con, &tag, &def, &tmp_len);
504     offset += (asn1p->offset - start);
505
506     /* INT */
507     /* wrapper */
508     start = asn1p->offset;
509     asn1_header_decode (asn1p, &cls, &con, &tag, &def, &tmp_len);
510     offset += (asn1p->offset - start);
511
512     if (type_off)
513         *type_off = offset;
514
515     /* value */
516     ret =  asn1_uint32_decode(asn1p, type, type_len);
517     if (ret != ASN1_ERR_NOERROR) {
518         fprintf(stderr,"die: type_value_pair: type, %s\n", to_error_str(ret));
519         return;
520     }
521     offset += tmp_len;
522
523     /* OCTET STRING (or generic data) */
524     /* wrapper */
525     start = asn1p->offset;
526     asn1_header_decode (asn1p, &cls, &con, &tag, &def, val_len);
527     asn1_header_decode (asn1p, &cls, &con, &tag, &def, val_len);
528     offset += asn1p->offset - start;
529     
530     if (val_off)
531         *val_off = offset;
532
533     /* value */
534     asn1_string_value_decode (asn1p, *val_len, val);
535
536     *inoff = offset + *val_len;
537 }
538
539 static gboolean
540 dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
541 {
542     int offset = 0;
543     proto_tree *kerberos_tree = NULL;
544     proto_tree *etype_tree = NULL;
545     proto_tree *preauth_tree = NULL;
546     proto_tree *request_tree = NULL;
547     proto_tree *additional_tickets_tree = NULL;
548     ASN1_SCK asn1, *asn1p = &asn1;
549     proto_item *item = NULL;
550
551     gint length;
552     guint cls, con, tag;
553     gboolean def;
554     gint item_len;
555     guint total_len;
556     int start, end, message_end, sequence_end;
557
558     int ret;
559
560     guint protocol_message_type;
561     
562     guint32 version;
563     guint32 msg_type;
564     guint32 preauth_type;
565     guint32 tmp_int;
566
567     /* simple holders */
568     int str_len;
569     guchar *str;
570     int tmp_pos1, tmp_pos2;
571
572     asn1_open(&asn1, tvb, 0);
573
574     /* top header */
575     KRB_HEAD_DECODE_OR_DIE("top");
576     protocol_message_type = tag;
577     if (tree) {
578         item = proto_tree_add_item(tree, proto_kerberos, tvb, offset,
579                                    item_len, FALSE);
580         kerberos_tree = proto_item_add_subtree(item, ett_kerberos);
581     }
582     message_end = asn1p->offset + item_len;
583     
584     /* second header */
585     KRB_HEAD_DECODE_OR_DIE("top2");
586
587     /* version number */
588     KRB_HEAD_DECODE_OR_DIE("version-wrap");
589     KRB_DECODE_UINT32_OR_DIE("version", version);
590
591     if (kerberos_tree) {
592         proto_tree_add_text(kerberos_tree, tvb, offset, length,
593                             "Version: %d",
594                             version);
595     }
596     offset += length;
597
598     /* message type */
599     KRB_HEAD_DECODE_OR_DIE("message-type-wrap");
600     KRB_DECODE_UINT32_OR_DIE("message-type", msg_type);
601
602     if (kerberos_tree) {
603         proto_tree_add_text(kerberos_tree, tvb, offset, length,
604                             "MSG Type: %s",
605                             val_to_str(msg_type, krb5_msg_types,
606                                        "Unknown msg type %#x"));
607     }
608     offset += length;
609
610     if (check_col(pinfo->cinfo, COL_INFO))
611         col_add_str(pinfo->cinfo, COL_INFO, val_to_str(msg_type, krb5_msg_types,
612                                              "Unknown msg type %#x"));
613
614         /* is preauthentication present? */
615     KRB_HEAD_DECODE_OR_DIE("padata-or-body");
616     if (((protocol_message_type == KRB5_MSG_AS_REQ ||
617           protocol_message_type == KRB5_MSG_TGS_REQ) &&
618          tag == KRB5_KDC_REQ_PADATA) ||
619         ((protocol_message_type == KRB5_MSG_AS_REP ||
620           protocol_message_type == KRB5_MSG_TGS_REP) &&
621          tag == KRB5_KDC_REP_PADATA)) {
622         /* pre-authentication supplied */
623
624         if (tree) {
625             item = proto_tree_add_text(kerberos_tree, tvb, offset,
626                                        item_len, "Pre-Authentication");
627             preauth_tree = proto_item_add_subtree(item, ett_preauth);
628         }
629
630         KRB_HEAD_DECODE_OR_DIE("sequence of pa-data");
631         end = asn1p->offset + item_len;
632
633         while(asn1p->offset < end) {
634             dissect_type_value_pair(asn1p, &offset,
635                                     &preauth_type, &item_len, &tmp_pos1,
636                                     &str, &str_len, &tmp_pos2);
637
638             if (preauth_tree) {
639                 proto_tree_add_text(preauth_tree, tvb, tmp_pos1,
640                                     item_len, "Type: %s",
641                                     val_to_str(preauth_type,
642                                                krb5_preauthentication_types,
643                                                "Unknown preauth type %#x"));
644                 proto_tree_add_text(preauth_tree, tvb, tmp_pos2,
645                                     str_len, "Value: %s",
646                                     bytes_to_str(str, str_len));
647             }
648         }
649         KRB_HEAD_DECODE_OR_DIE("message-body");
650     }
651
652     switch (protocol_message_type) {
653
654     case KRB5_MSG_AS_REQ:
655     case KRB5_MSG_TGS_REQ:
656 /*
657   AS-REQ ::=         [APPLICATION 10] KDC-REQ
658   TGS-REQ ::=        [APPLICATION 12] KDC-REQ
659     
660   KDC-REQ ::=        SEQUENCE {
661            pvno[1]               INTEGER,
662            msg-type[2]           INTEGER,
663            padata[3]             SEQUENCE OF PA-DATA OPTIONAL,
664            req-body[4]           KDC-REQ-BODY
665   }
666
667   KDC-REQ-BODY ::=   SEQUENCE {
668             kdc-options[0]       KDCOptions,
669             cname[1]             PrincipalName OPTIONAL,
670                          -- Used only in AS-REQ
671             realm[2]             Realm, -- Server's realm
672                          -- Also client's in AS-REQ
673             sname[3]             PrincipalName OPTIONAL,
674             from[4]              KerberosTime OPTIONAL,
675             till[5]              KerberosTime,
676             rtime[6]             KerberosTime OPTIONAL,
677             nonce[7]             INTEGER,
678             etype[8]             SEQUENCE OF INTEGER, -- EncryptionType,
679                          -- in preference order
680             addresses[9]         HostAddresses OPTIONAL,
681             enc-authorization-data[10]   EncryptedData OPTIONAL,
682                          -- Encrypted AuthorizationData encoding
683             additional-tickets[11]       SEQUENCE OF Ticket OPTIONAL
684   }
685
686 */
687         /* request body */
688         KRB_HEAD_DECODE_OR_DIE("body-sequence");
689         if (tree) {
690             item = proto_tree_add_text(kerberos_tree, tvb, offset,
691                                        item_len, "Request");
692             request_tree = proto_item_add_subtree(item, ett_request);
693         }
694         sequence_end = asn1p->offset + item_len;
695
696         /* kdc options */
697         KRB_HEAD_DECODE_OR_DIE("kdc options");
698
699         KRB_HEAD_DECODE_OR_DIE("kdc options:bits");
700
701         if (request_tree) {
702                 proto_tree_add_text(request_tree, tvb, offset, item_len,
703                                     "Options: %s",
704                                     tvb_bytes_to_str(asn1p->tvb, asn1p->offset,
705                                                      item_len));
706         }
707         offset += item_len;
708         asn1p->offset += item_len;
709
710         KRB_HEAD_DECODE_OR_DIE("Client Name or Realm");
711
712         if (CHECK_CONTEXT_TYPE(KRB5_BODY_CNAME)) {
713             item_len = dissect_PrincipalName("Client Name", asn1p, pinfo,
714                                              request_tree, offset);
715             if (item_len == -1)
716                 return -1;
717             offset += item_len;
718             KRB_HEAD_DECODE_OR_DIE("Realm");
719         }
720
721         DIE_IF_NOT_CONTEXT_TYPE("Realm", KRB5_BODY_REALM);
722         KRB_DECODE_GENERAL_STRING_OR_DIE("Realm", str, str_len, item_len);
723         if (request_tree) {
724             proto_tree_add_text(request_tree, tvb, offset, item_len,
725                                 "Realm: %.*s", str_len, str);
726         }
727         offset += item_len;
728
729         KRB_HEAD_DECODE_OR_DIE("Server Name");
730         if (CHECK_CONTEXT_TYPE(KRB5_BODY_SNAME)) {
731             item_len = dissect_PrincipalName("Server Name", asn1p, pinfo,
732                                              request_tree, offset);
733             if (item_len == -1)
734                 return -1;
735             offset += item_len;
736             KRB_HEAD_DECODE_OR_DIE("From or Till");
737         }
738
739         if (CHECK_CONTEXT_TYPE(KRB5_BODY_FROM)) {
740             KRB_DECODE_GENERAL_TIME_OR_DIE("From", str, str_len, item_len);
741             krb_proto_tree_add_time(request_tree, asn1p->tvb, offset, item_len,
742                                     "Start Time", str);
743             offset += item_len;
744             KRB_HEAD_DECODE_OR_DIE("Till");
745         }
746
747         DIE_IF_NOT_CONTEXT_TYPE("Till", KRB5_BODY_TILL);
748         KRB_DECODE_GENERAL_TIME_OR_DIE("Till", str, str_len, item_len);
749         krb_proto_tree_add_time(request_tree, asn1p->tvb, offset, item_len,
750                                 "End Time", str);
751         offset += item_len;
752
753         KRB_HEAD_DECODE_OR_DIE("Renewable Until or Nonce");
754         if (CHECK_CONTEXT_TYPE(KRB5_BODY_RTIME)) {
755             KRB_DECODE_GENERAL_TIME_OR_DIE("Renewable Until", str, str_len, item_len);
756             krb_proto_tree_add_time(request_tree, asn1p->tvb, offset, item_len,
757                                     "Renewable Until", str);
758             offset += item_len;
759             KRB_HEAD_DECODE_OR_DIE("Nonce");
760         }
761             
762         DIE_IF_NOT_CONTEXT_TYPE("Nonce", KRB5_BODY_NONCE);
763         KRB_DECODE_UINT32_OR_DIE("Nonce", tmp_int);
764         if (request_tree) {
765             proto_tree_add_text(request_tree, tvb, offset, length,
766                                 "Random Number: %u",
767                                 tmp_int);
768         }
769         offset += length;
770         
771         KRB_DECODE_CONTEXT_HEAD_OR_DIE("encryption type spot",
772                                               KRB5_BODY_ENCTYPE);
773         KRB_HEAD_DECODE_OR_DIE("encryption type list");
774         if (kerberos_tree) {
775             item = proto_tree_add_text(request_tree, tvb, offset,
776                                        item_len, "Encryption Types");
777             etype_tree = proto_item_add_subtree(item, ett_etype);
778         }
779         total_len = item_len;
780         while(total_len > 0) {
781             KRB_DECODE_UINT32_OR_DIE("encryption type", tmp_int);
782             if (etype_tree) {
783                 proto_tree_add_text(etype_tree, tvb, offset, length,
784                                     "Type: %s",
785                                     val_to_str(tmp_int,
786                                                krb5_encryption_types,
787                                                "Unknown encryption type %#x"));
788             }
789             offset += length;
790             total_len -= length;
791         }
792
793         if (asn1p->offset >= sequence_end)
794             break;
795         KRB_HEAD_DECODE_OR_DIE("addresses or enc-authorization-data");
796         if (CHECK_CONTEXT_TYPE(KRB5_BODY_ADDRESSES)) {
797             /* addresses supplied */
798
799             length = dissect_Addresses("Addresses", asn1p, pinfo, kerberos_tree,
800                                        offset);
801             if (offset == -1)
802                 return -1;
803             offset += length;
804             if (asn1p->offset >= sequence_end)
805                 break;
806             KRB_HEAD_DECODE_OR_DIE("enc-authorization-data or additional-tickets");
807         }
808
809         if (CHECK_CONTEXT_TYPE(KRB5_BODY_ENC_AUTHORIZATION_DATA)) {
810             /* enc-authorization-data supplied */
811             length = dissect_EncryptedData("Encrypted Payload", asn1p, pinfo,
812                                            kerberos_tree, offset);
813             if (length == -1)
814                 return -1;
815             offset += length;
816             if (asn1p->offset >= sequence_end)
817                 break;
818             KRB_HEAD_DECODE_OR_DIE("additional-tickets");
819         }
820
821         /* additional-tickets supplied */
822         if (tree) {
823             item = proto_tree_add_text(kerberos_tree, tvb, offset,
824                                        item_len, "Additional Tickets");
825             additional_tickets_tree = proto_item_add_subtree(item, ett_additional_tickets);
826         }
827         end = asn1p->offset + item_len;
828         while(asn1p->offset < end) {
829             KRB_DECODE_CONTEXT_HEAD_OR_DIE("ticket", KRB5_KDC_REP_TICKET);
830             length = dissect_Ticket("ticket", asn1p, pinfo, additional_tickets_tree,
831                                     offset);
832             if (length == -1)
833                 return -1;
834             offset += length;
835         }
836
837         break;
838
839     case KRB5_MSG_AS_REP:
840     case KRB5_MSG_TGS_REP:
841 /*
842    AS-REP ::=    [APPLICATION 11] KDC-REP
843    TGS-REP ::=   [APPLICATION 13] KDC-REP
844
845    KDC-REP ::=   SEQUENCE {
846                  pvno[0]                    INTEGER,
847                  msg-type[1]                INTEGER,
848                  padata[2]                  SEQUENCE OF PA-DATA OPTIONAL,
849                  crealm[3]                  Realm,
850                  cname[4]                   PrincipalName,
851                  ticket[5]                  Ticket,
852                  enc-part[6]                EncryptedData
853    }
854 */
855
856         DIE_IF_NOT_CONTEXT_TYPE("crealm", KRB5_KDC_REP_CREALM);
857         KRB_DECODE_GENERAL_STRING_OR_DIE("realm name", str, str_len, item_len);
858         if (kerberos_tree) {
859             proto_tree_add_text(kerberos_tree, tvb, offset, item_len,
860                                 "Realm: %.*s", str_len, str);
861         }
862         offset += item_len;
863
864         KRB_DECODE_CONTEXT_HEAD_OR_DIE("cname", KRB5_KDC_REP_CNAME);
865         item_len = dissect_PrincipalName("Client Name", asn1p, pinfo,
866                                          kerberos_tree, offset);
867         if (item_len == -1)
868             return -1;
869         offset += item_len;
870         
871         KRB_DECODE_CONTEXT_HEAD_OR_DIE("ticket", KRB5_KDC_REP_TICKET);
872         length = dissect_Ticket("ticket", asn1p, pinfo, kerberos_tree, offset);
873         if (length == -1)
874             return -1;
875         offset += length;
876
877         KRB_DECODE_CONTEXT_HEAD_OR_DIE("enc-msg-part",
878                                               KRB5_KDC_REP_ENC_PART);
879         length = dissect_EncryptedData("Encrypted Payload", asn1p, pinfo,
880                                        kerberos_tree, offset);
881         if (length == -1)
882             return -1;
883         offset += length;
884         break;
885
886     case KRB5_MSG_ERROR:
887 /*
888   KRB-ERROR ::=   [APPLICATION 30] SEQUENCE {
889                    pvno[0]               INTEGER,
890                    msg-type[1]           INTEGER,
891                    ctime[2]              KerberosTime OPTIONAL,
892                    cusec[3]              INTEGER OPTIONAL,
893                    stime[4]              KerberosTime,
894                    susec[5]              INTEGER,
895                    error-code[6]         INTEGER,
896                    crealm[7]             Realm OPTIONAL,
897                    cname[8]              PrincipalName OPTIONAL,
898                    realm[9]              Realm, -- Correct realm
899                    sname[10]             PrincipalName, -- Correct name
900                    e-text[11]            GeneralString OPTIONAL,
901                    e-data[12]            OCTET STRING OPTIONAL
902    }
903   }
904
905 */
906
907         /* ctime */
908         if (CHECK_CONTEXT_TYPE(KRB5_ERROR_CTIME)) {
909             KRB_DECODE_GENERAL_TIME_OR_DIE("ctime", str, str_len, item_len);
910             krb_proto_tree_add_time(kerberos_tree, asn1p->tvb, offset, item_len,
911                                     "ctime", str);
912             offset += item_len;
913                         KRB_HEAD_DECODE_OR_DIE("cusec");
914         }
915
916         /* cusec */
917         if (CHECK_CONTEXT_TYPE(KRB5_ERROR_CUSEC)) {
918                         KRB_DECODE_UINT32_OR_DIE("cusec", tmp_int);
919             if (kerberos_tree) {
920                 proto_tree_add_text(kerberos_tree, tvb, offset, length,
921                                     "cusec: %u",
922                                     tmp_int);
923             }
924
925             offset += item_len;
926                         KRB_HEAD_DECODE_OR_DIE("sutime");
927         }
928
929         DIE_IF_NOT_CONTEXT_TYPE("sutime", KRB5_ERROR_STIME);
930         KRB_DECODE_GENERAL_TIME_OR_DIE("stime", str, str_len, item_len);
931         krb_proto_tree_add_time(kerberos_tree, asn1p->tvb, offset, item_len,
932                                     "stime", str);
933         offset += item_len;
934
935         KRB_HEAD_DECODE_OR_DIE("susec");
936         DIE_IF_NOT_CONTEXT_TYPE("susec", KRB5_ERROR_SUSEC);             
937         KRB_DECODE_UINT32_OR_DIE("susec", tmp_int);
938         if (kerberos_tree) {
939                 proto_tree_add_text(kerberos_tree, tvb, offset, length,
940                                     "susec: %u",
941                                     tmp_int);
942         }
943         offset += item_len;
944
945         KRB_HEAD_DECODE_OR_DIE("errcode");
946         DIE_IF_NOT_CONTEXT_TYPE("errcode", KRB5_ERROR_ERROR_CODE);
947         KRB_DECODE_UINT32_OR_DIE("errcode", tmp_int);
948         if (kerberos_tree) {
949             proto_tree_add_text(kerberos_tree, tvb, offset, length,
950                                 "Error Code: %s",
951                                 val_to_str(tmp_int, krb5_error_codes,
952                                            "Unknown error code %#x"));
953         }
954         offset += item_len;
955         KRB_HEAD_DECODE_OR_DIE("crealm");
956
957         if (CHECK_CONTEXT_TYPE(KRB5_ERROR_CREALM)) {
958                 KRB_DECODE_GENERAL_STRING_OR_DIE("crealm", str, str_len, item_len);
959                 if (kerberos_tree) {
960                     proto_tree_add_text(kerberos_tree, tvb, offset, item_len,
961                                         "crealm: %.*s", str_len, str);
962                 }
963                 offset += item_len;
964                 KRB_HEAD_DECODE_OR_DIE("cname");
965         }
966
967         if (CHECK_CONTEXT_TYPE(KRB5_ERROR_CNAME)) {
968             item_len = dissect_PrincipalName("cname", asn1p, pinfo,
969                                          kerberos_tree, offset);
970             if (item_len == -1)
971                 return -1;
972             offset += item_len;
973             KRB_HEAD_DECODE_OR_DIE("realm");
974         }
975
976         DIE_IF_NOT_CONTEXT_TYPE("realm", KRB5_ERROR_REALM);
977         KRB_DECODE_GENERAL_STRING_OR_DIE("realm", str, str_len, item_len);
978         if (kerberos_tree) {
979             proto_tree_add_text(kerberos_tree, tvb, offset, item_len,
980                                 "realm: %.*s", str_len, str);
981         }
982         offset += item_len;
983         KRB_HEAD_DECODE_OR_DIE("sname");
984
985         DIE_IF_NOT_CONTEXT_TYPE("sname", KRB5_ERROR_SNAME);
986         item_len = dissect_PrincipalName("sname", asn1p, pinfo,
987                                          kerberos_tree, offset);
988         if (item_len == -1)
989                 return -1;
990         offset += item_len;
991
992         if (asn1p->offset >= message_end)
993             break;
994         KRB_HEAD_DECODE_OR_DIE("e-text");
995         if ( CHECK_CONTEXT_TYPE(KRB5_ERROR_ETEXT) ) {
996             KRB_DECODE_GENERAL_STRING_OR_DIE("etext", str, str_len, item_len);
997             if (kerberos_tree) {
998                 proto_tree_add_text(kerberos_tree, tvb, offset, item_len,
999                                         "etext: %.*s", str_len, str);
1000             }
1001             offset += item_len;
1002             if (asn1p->offset >= message_end)
1003                 break;
1004             KRB_HEAD_DECODE_OR_DIE("e-data");
1005         }
1006
1007         if ( CHECK_CONTEXT_TYPE(KRB5_ERROR_EDATA) ) {
1008             guchar *data;
1009             guint data_len;
1010
1011             KRB_DECODE_OCTET_STRING_OR_DIE("e-data", data, data_len, item_len);
1012
1013             if (kerberos_tree) {
1014                 proto_tree_add_text(kerberos_tree, tvb, offset, data_len,
1015                             "Error Data: %s", bytes_to_str(data, item_len));
1016             }
1017             offset += data_len;
1018         }
1019
1020         break;
1021     }
1022     return offset;
1023 }
1024
1025 static void
1026 dissect_kerberos(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1027 {
1028     if (check_col(pinfo->cinfo, COL_PROTOCOL))
1029         col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
1030
1031     dissect_kerberos_main(tvb, pinfo, tree);
1032 }
1033
1034 static int
1035 dissect_PrincipalName(char *title, ASN1_SCK *asn1p, packet_info *pinfo,
1036                        proto_tree *tree, int start_offset)
1037 {
1038 /*
1039    PrincipalName ::=   SEQUENCE {
1040                        name-type[0]     INTEGER,
1041                        name-string[1]   SEQUENCE OF GeneralString
1042    }
1043 */
1044     proto_tree *princ_tree = NULL;
1045     int offset = start_offset;
1046
1047     guint32 princ_type;
1048
1049     int start;
1050     guint cls, con, tag;
1051     guint header_len, item_len, total_len, type_len;
1052     int ret;
1053
1054     proto_item *item = NULL;
1055     guint length;
1056     gboolean def;
1057
1058     int type_offset;
1059
1060     guchar *name;
1061     guint name_len;
1062
1063     /* principal name */
1064     KRB_SEQ_HEAD_DECODE_OR_DIE("principal section");
1065
1066     if (tree) {
1067       item = proto_tree_add_text(tree, asn1p->tvb, start_offset,
1068                                  (offset - start_offset) + item_len, "%s",
1069                                  title);
1070       princ_tree = proto_item_add_subtree(item, ett_princ);
1071     } else {
1072       item = NULL;
1073       princ_tree = NULL;
1074     }
1075
1076     KRB_DECODE_CONTEXT_HEAD_OR_DIE("principal type", 0);
1077     KRB_DECODE_UINT32_OR_DIE("princ-type", princ_type);
1078     type_offset = offset;
1079     type_len = item_len;
1080     offset += length;
1081
1082     if (princ_tree) {
1083       proto_tree_add_text(princ_tree, asn1p->tvb, type_offset, type_len,
1084                                                 "Type: %s",
1085                                                 val_to_str(princ_type, krb5_princ_types,
1086                                            "Unknown name type %#x"));
1087     }
1088
1089     KRB_DECODE_CONTEXT_HEAD_OR_DIE("principal name-string", 1);
1090     KRB_SEQ_HEAD_DECODE_OR_DIE("principal name-string sequence-of");
1091     total_len = item_len;
1092     if (total_len == 0) {
1093       /* There are no name strings in this PrincipalName, so we can't
1094          put any in the top-level item. */
1095       return offset - start_offset;
1096     }
1097
1098     /* Put the first name string in the top-level item. */
1099     KRB_DECODE_GENERAL_STRING_OR_DIE("principal name", name, name_len, item_len);
1100     if (princ_tree) {
1101         proto_item_set_text(item, "%s: %.*s", title, (int) name_len, name);
1102         proto_tree_add_text(princ_tree, asn1p->tvb, offset, item_len,
1103                             "Name: %.*s", (int) name_len, name);
1104     }
1105     total_len -= item_len;
1106     offset += item_len;
1107
1108     /* Now process the rest of the strings.
1109        XXX - put them in the item as well? */
1110     while (total_len > 0) {
1111         KRB_DECODE_GENERAL_STRING_OR_DIE("principal name", name, name_len, item_len);
1112         if (princ_tree) {
1113             proto_tree_add_text(princ_tree, asn1p->tvb, offset, item_len,
1114                                 "Name: %.*s", (int) name_len, name);
1115         }
1116         total_len -= item_len;
1117         offset += item_len;
1118     }
1119     return offset - start_offset;
1120 }
1121
1122 static int
1123 dissect_Addresses(char *title, ASN1_SCK *asn1p, packet_info *pinfo,
1124                   proto_tree *tree, int start_offset) {
1125     proto_tree *address_tree = NULL;
1126     int offset = start_offset;
1127
1128     int start, end;
1129     guint cls, con, tag;
1130     guint item_len;
1131     int ret;
1132
1133     proto_item *item = NULL;
1134     gboolean def;
1135
1136     int tmp_pos1, tmp_pos2;
1137     guint32 address_type;
1138
1139     int str_len;
1140     guchar *str;
1141
1142     KRB_HEAD_DECODE_OR_DIE("sequence of addresses");
1143     if (tree) {
1144         item = proto_tree_add_text(tree, asn1p->tvb, offset,
1145                                    item_len, "Addresses");
1146         address_tree = proto_item_add_subtree(item, ett_addresses);
1147     }
1148
1149     start = offset;
1150     end = asn1p->offset + item_len;
1151
1152     while(asn1p->offset < end) {
1153         dissect_type_value_pair(asn1p, &offset,
1154                                 &address_type, &item_len, &tmp_pos1,
1155                                 &str, &str_len, &tmp_pos2);
1156
1157         if (address_tree) {
1158             proto_tree_add_text(address_tree, asn1p->tvb, tmp_pos1,
1159                                 item_len, "Type: %s",
1160                                 val_to_str(address_type, krb5_address_types,
1161                                            "Unknown address type %#x"));
1162             switch(address_type) {
1163                 case KRB5_ADDR_IPv4:
1164                     proto_tree_add_text(address_tree, asn1p->tvb, tmp_pos2,
1165                                         str_len, "Value: %d.%d.%d.%d",
1166                                         str[0], str[1], str[2], str[3]);
1167                     break;
1168                     
1169                 default:
1170                     proto_tree_add_text(address_tree, asn1p->tvb, tmp_pos2,
1171                                         str_len, "Value: %s",
1172                                         bytes_to_str(str, str_len));
1173             }
1174         }
1175     }
1176     
1177     return offset - start_offset;
1178 }
1179
1180 static int
1181 dissect_EncryptedData(char *title, ASN1_SCK *asn1p, packet_info *pinfo,
1182                       proto_tree *tree, int start_offset)
1183 {
1184 /*
1185    EncryptedData ::=   SEQUENCE {
1186                        etype[0]     INTEGER, -- EncryptionType
1187                        kvno[1]      INTEGER OPTIONAL,
1188                        cipher[2]    OCTET STRING -- ciphertext
1189    }
1190 */
1191     proto_tree *encr_tree = NULL;
1192     int offset = start_offset;
1193
1194     int start;
1195     guint cls, con, tag;
1196     guint header_len, item_len, data_len;
1197     int ret;
1198
1199     proto_item *item = NULL;
1200     guint length;
1201     gboolean def;
1202     guint32 val;
1203
1204     guchar *data;
1205
1206     KRB_SEQ_HEAD_DECODE_OR_DIE("encrypted data section");
1207
1208     if (tree) {
1209         item = proto_tree_add_text(tree, asn1p->tvb, start_offset,
1210                                    (offset - start_offset) + item_len,
1211                                    "Encrypted Data: %s", title);
1212         encr_tree = proto_item_add_subtree(item, ett_princ);
1213     }
1214
1215     /* type */
1216     KRB_DECODE_CONTEXT_HEAD_OR_DIE("encryption type", 0);
1217     KRB_DECODE_UINT32_OR_DIE("encr-type", val);
1218     if (encr_tree) {
1219         proto_tree_add_text(encr_tree, asn1p->tvb, offset, length,
1220                             "Type: %s",
1221                             val_to_str(val, krb5_encryption_types,
1222                                        "Unknown encryption type %#x"));
1223     }
1224     offset += length;
1225
1226     /* kvno */
1227     KRB_HEAD_DECODE_OR_DIE("kvno-wrap or cipher-wrap");
1228     if (CHECK_CONTEXT_TYPE(1)) {
1229       KRB_DECODE_UINT32_OR_DIE("kvno", val);
1230       if (encr_tree) {
1231           proto_tree_add_text(encr_tree, asn1p->tvb, offset, length,
1232                               "KVNO: %d", val);
1233       }
1234       offset += length;
1235       KRB_HEAD_DECODE_OR_DIE("cipher-wrap");
1236     }
1237
1238     DIE_IF_NOT_CONTEXT_TYPE("cipher-wrap", 2);
1239     KRB_DECODE_OCTET_STRING_OR_DIE("cipher", data, data_len, item_len);
1240
1241     if (encr_tree) {
1242         proto_tree_add_text(encr_tree, asn1p->tvb, offset, data_len,
1243                             "CipherText: %s", bytes_to_str(data, item_len));
1244     }
1245     offset += data_len;
1246     
1247     return offset - start_offset;
1248 }
1249
1250 static int
1251 dissect_Ticket(char *title, ASN1_SCK *asn1p, packet_info *pinfo,
1252                proto_tree *tree, int start_offset)
1253 {
1254 /*
1255    Ticket ::=                    [APPLICATION 1] SEQUENCE {
1256                                  tkt-vno[0]                   INTEGER,
1257                                  realm[1]                     Realm,
1258                                  sname[2]                     PrincipalName,
1259                                  enc-part[3]                  EncryptedData
1260    }
1261 */
1262     proto_tree *ticket_tree = NULL;
1263     int offset = start_offset;
1264
1265     int start;
1266     guint cls, con, tag;
1267     guint header_len, total_len;
1268     gint item_len;
1269     int ret;
1270
1271     proto_item *item = NULL;
1272     gint length;
1273     gboolean def;
1274     guint32 val;
1275
1276     int str_len;
1277     guchar *str;
1278
1279     KRB_DECODE_APPLICATION_TAGGED_HEAD_OR_DIE("Ticket section", 1);
1280     KRB_SEQ_HEAD_DECODE_OR_DIE("Ticket sequence");
1281     total_len = item_len;
1282
1283     if (tree) {
1284         item = proto_tree_add_text(tree, asn1p->tvb, start_offset,
1285                                    (offset - start_offset) + item_len,
1286                                    "Ticket");
1287         ticket_tree = proto_item_add_subtree(item, ett_ticket);
1288     }
1289
1290     /* type */
1291     KRB_DECODE_CONTEXT_HEAD_OR_DIE("Ticket tkt-vno", KRB5_TKT_TKT_VNO);
1292     KRB_DECODE_UINT32_OR_DIE("Ticket tkt-vno", val);
1293     if (ticket_tree) {
1294         proto_tree_add_text(ticket_tree, asn1p->tvb, offset, length,
1295                             "Version: %u", val);
1296     }
1297     offset += length;
1298     total_len -= length;
1299
1300     /* realm name */
1301     KRB_DECODE_CONTEXT_HEAD_OR_DIE("Ticket realm", KRB5_TKT_REALM);
1302     KRB_DECODE_GENERAL_STRING_OR_DIE("Ticket realm string", str, str_len, item_len);
1303     if (ticket_tree) {
1304         proto_tree_add_text(ticket_tree, asn1p->tvb, offset, item_len,
1305                             "Realm: %.*s", str_len, str);
1306     }
1307     offset += item_len;
1308     total_len -= item_len;
1309
1310     /* server name (sname) */
1311     KRB_DECODE_CONTEXT_HEAD_OR_DIE("Ticket sname", KRB5_TKT_SNAME);
1312     item_len = dissect_PrincipalName("Service Name", asn1p, pinfo, ticket_tree,
1313                                      offset);
1314     if (item_len == -1)
1315         return -1;
1316     offset += item_len;
1317
1318     /* encrypted part */
1319     KRB_DECODE_CONTEXT_HEAD_OR_DIE("enc-part", KRB5_TKT_ENC_PART);
1320     length = dissect_EncryptedData("Ticket data", asn1p, pinfo, ticket_tree,
1321                                    offset);
1322     if (length == -1)
1323         return -1;
1324     offset += length;
1325
1326     return offset - start_offset;
1327 }
1328
1329
1330 void
1331 proto_register_kerberos(void) {
1332 /*
1333     static hf_register_info hf[] = {
1334     };
1335 */
1336     static gint *ett[] = {
1337         &ett_kerberos,
1338         &ett_preauth,
1339         &ett_request,
1340         &ett_princ,
1341         &ett_encrypted,
1342         &ett_ticket,
1343         &ett_addresses,
1344         &ett_etype,
1345         &ett_additional_tickets,
1346     };
1347     proto_kerberos = proto_register_protocol("Kerberos", "KRB5", "kerberos");
1348 /*
1349     proto_register_field_array(proto_kerberos, hf, array_length(hf));
1350 */
1351     proto_register_subtree_array(ett, array_length(ett));
1352 }
1353
1354 void
1355 proto_reg_handoff_kerberos(void)
1356 {
1357     dissector_handle_t kerberos_handle;
1358
1359     kerberos_handle = create_dissector_handle(dissect_kerberos, proto_kerberos);
1360     dissector_add("udp.port", UDP_PORT_KERBEROS, kerberos_handle);
1361     dissector_add("tcp.port", TCP_PORT_KERBEROS, kerberos_handle);
1362 }
1363
1364 /*
1365
1366   MISC definitions from RFC1510:
1367   
1368    Realm ::=           GeneralString
1369
1370    KerberosTime ::=   GeneralizedTime
1371
1372    HostAddress ::=    SEQUENCE  {
1373                       addr-type[0]             INTEGER,
1374                       address[1]               OCTET STRING
1375    }
1376
1377    HostAddresses ::=   SEQUENCE OF SEQUENCE {
1378                        addr-type[0]             INTEGER,
1379                        address[1]               OCTET STRING
1380    }
1381
1382    AuthorizationData ::=   SEQUENCE OF SEQUENCE {
1383                            ad-type[0]               INTEGER,
1384                            ad-data[1]               OCTET STRING
1385    }
1386                    APOptions ::=   BIT STRING {
1387                                    reserved(0),
1388                                    use-session-key(1),
1389                                    mutual-required(2)
1390                    }
1391
1392
1393                    TicketFlags ::=   BIT STRING {
1394                                      reserved(0),
1395                                      forwardable(1),
1396                                      forwarded(2),
1397                                      proxiable(3),
1398                                      proxy(4),
1399                                      may-postdate(5),
1400                                      postdated(6),
1401                                      invalid(7),
1402                                      renewable(8),
1403                                      initial(9),
1404                                      pre-authent(10),
1405                                      hw-authent(11)
1406                    }
1407
1408                   KDCOptions ::=   BIT STRING {
1409                                    reserved(0),
1410                                    forwardable(1),
1411                                    forwarded(2),
1412                                    proxiable(3),
1413                                    proxy(4),
1414                                    allow-postdate(5),
1415                                    postdated(6),
1416                                    unused7(7),
1417                                    renewable(8),
1418                                    unused9(9),
1419                                    unused10(10),
1420                                    unused11(11),
1421                                    renewable-ok(27),
1422                                    enc-tkt-in-skey(28),
1423                                    renew(30),
1424                                    validate(31)
1425                   }
1426
1427
1428             LastReq ::=   SEQUENCE OF SEQUENCE {
1429                           lr-type[0]               INTEGER,
1430                           lr-value[1]              KerberosTime
1431             }
1432
1433    Ticket ::=                    [APPLICATION 1] SEQUENCE {
1434                                  tkt-vno[0]                   INTEGER,
1435                                  realm[1]                     Realm,
1436                                  sname[2]                     PrincipalName,
1437                                  enc-part[3]                  EncryptedData
1438    }
1439
1440   -- Encrypted part of ticket
1441   EncTicketPart ::=     [APPLICATION 3] SEQUENCE {
1442                         flags[0]             TicketFlags,
1443                         key[1]               EncryptionKey,
1444                         crealm[2]            Realm,
1445                         cname[3]             PrincipalName,
1446                         transited[4]         TransitedEncoding,
1447                         authtime[5]          KerberosTime,
1448                         starttime[6]         KerberosTime OPTIONAL,
1449                         endtime[7]           KerberosTime,
1450                         renew-till[8]        KerberosTime OPTIONAL,
1451                         caddr[9]             HostAddresses OPTIONAL,
1452                         authorization-data[10]   AuthorizationData OPTIONAL
1453   }
1454
1455   -- encoded Transited field
1456   TransitedEncoding ::=         SEQUENCE {
1457                                 tr-type[0]  INTEGER, -- must be registered
1458                                 contents[1]          OCTET STRING
1459   }
1460
1461   -- Unencrypted authenticator
1462   Authenticator ::=    [APPLICATION 2] SEQUENCE    {
1463                  authenticator-vno[0]          INTEGER,
1464                  crealm[1]                     Realm,
1465                  cname[2]                      PrincipalName,
1466                  cksum[3]                      Checksum OPTIONAL,
1467                  cusec[4]                      INTEGER,
1468                  ctime[5]                      KerberosTime,
1469                  subkey[6]                     EncryptionKey OPTIONAL,
1470                  seq-number[7]                 INTEGER OPTIONAL,
1471                  authorization-data[8]         AuthorizationData OPTIONAL
1472   }
1473
1474   PA-DATA ::=        SEQUENCE {
1475            padata-type[1]        INTEGER,
1476            padata-value[2]       OCTET STRING,
1477                          -- might be encoded AP-REQ
1478   }
1479
1480    padata-type     ::= PA-ENC-TIMESTAMP
1481    padata-value    ::= EncryptedData -- PA-ENC-TS-ENC
1482
1483    PA-ENC-TS-ENC   ::= SEQUENCE {
1484            patimestamp[0]               KerberosTime, -- client's time
1485            pausec[1]                    INTEGER OPTIONAL
1486    }
1487
1488    EncASRepPart ::=    [APPLICATION 25[25]] EncKDCRepPart
1489    EncTGSRepPart ::=   [APPLICATION 26] EncKDCRepPart
1490
1491    EncKDCRepPart ::=   SEQUENCE {
1492                key[0]                       EncryptionKey,
1493                last-req[1]                  LastReq,
1494                nonce[2]                     INTEGER,
1495                key-expiration[3]            KerberosTime OPTIONAL,
1496                flags[4]                     TicketFlags,
1497                authtime[5]                  KerberosTime,
1498                starttime[6]                 KerberosTime OPTIONAL,
1499                endtime[7]                   KerberosTime,
1500                renew-till[8]                KerberosTime OPTIONAL,
1501                srealm[9]                    Realm,
1502                sname[10]                    PrincipalName,
1503                caddr[11]                    HostAddresses OPTIONAL
1504    }
1505
1506    AP-REQ ::=      [APPLICATION 14] SEQUENCE {
1507                    pvno[0]                       INTEGER,
1508                    msg-type[1]                   INTEGER,
1509                    ap-options[2]                 APOptions,
1510                    ticket[3]                     Ticket,
1511                    authenticator[4]              EncryptedData
1512    }
1513
1514    APOptions ::=   BIT STRING {
1515                    reserved(0),
1516                    use-session-key(1),
1517                    mutual-required(2)
1518    }
1519
1520    AP-REP ::=         [APPLICATION 15] SEQUENCE {
1521               pvno[0]                   INTEGER,
1522               msg-type[1]               INTEGER,
1523               enc-part[2]               EncryptedData
1524    }
1525
1526    EncAPRepPart ::=   [APPLICATION 27]     SEQUENCE {
1527               ctime[0]                  KerberosTime,
1528               cusec[1]                  INTEGER,
1529               subkey[2]                 EncryptionKey OPTIONAL,
1530               seq-number[3]             INTEGER OPTIONAL
1531    }
1532
1533    KRB-SAFE ::=        [APPLICATION 20] SEQUENCE {
1534                pvno[0]               INTEGER,
1535                msg-type[1]           INTEGER,
1536                safe-body[2]          KRB-SAFE-BODY,
1537                cksum[3]              Checksum
1538    }
1539
1540    KRB-SAFE-BODY ::=   SEQUENCE {
1541                user-data[0]          OCTET STRING,
1542                timestamp[1]          KerberosTime OPTIONAL,
1543                usec[2]               INTEGER OPTIONAL,
1544                seq-number[3]         INTEGER OPTIONAL,
1545                s-address[4]          HostAddress,
1546                r-address[5]          HostAddress OPTIONAL
1547    }
1548
1549    KRB-PRIV ::=         [APPLICATION 21] SEQUENCE {
1550                 pvno[0]                   INTEGER,
1551                 msg-type[1]               INTEGER,
1552                 enc-part[3]               EncryptedData
1553    }
1554
1555    EncKrbPrivPart ::=   [APPLICATION 28] SEQUENCE {
1556                 user-data[0]              OCTET STRING,
1557                 timestamp[1]              KerberosTime OPTIONAL,
1558                 usec[2]                   INTEGER OPTIONAL,
1559                 seq-number[3]             INTEGER OPTIONAL,
1560                 s-address[4]              HostAddress, -- sender's addr
1561                 r-address[5]              HostAddress OPTIONAL
1562                                                       -- recip's addr
1563    }
1564
1565    KRB-CRED         ::= [APPLICATION 22]   SEQUENCE {
1566                     pvno[0]                INTEGER,
1567                     msg-type[1]            INTEGER, -- KRB_CRED
1568                     tickets[2]             SEQUENCE OF Ticket,
1569                     enc-part[3]            EncryptedData
1570    }
1571
1572    EncKrbCredPart   ::= [APPLICATION 29]   SEQUENCE {
1573                     ticket-info[0]         SEQUENCE OF KrbCredInfo,
1574                     nonce[1]               INTEGER OPTIONAL,
1575                     timestamp[2]           KerberosTime OPTIONAL,
1576                     usec[3]                INTEGER OPTIONAL,
1577                     s-address[4]           HostAddress OPTIONAL,
1578                     r-address[5]           HostAddress OPTIONAL
1579    }
1580
1581    KrbCredInfo      ::=                    SEQUENCE {
1582                     key[0]                 EncryptionKey,
1583                     prealm[1]              Realm OPTIONAL,
1584                     pname[2]               PrincipalName OPTIONAL,
1585                     flags[3]               TicketFlags OPTIONAL,
1586                     authtime[4]            KerberosTime OPTIONAL,
1587                     starttime[5]           KerberosTime OPTIONAL,
1588                     endtime[6]             KerberosTime OPTIONAL
1589                     renew-till[7]          KerberosTime OPTIONAL,
1590                     srealm[8]              Realm OPTIONAL,
1591                     sname[9]               PrincipalName OPTIONAL,
1592                     caddr[10]              HostAddresses OPTIONAL
1593    }
1594
1595    KRB-ERROR ::=   [APPLICATION 30] SEQUENCE {
1596                    pvno[0]               INTEGER,
1597                    msg-type[1]           INTEGER,
1598                    ctime[2]              KerberosTime OPTIONAL,
1599                    cusec[3]              INTEGER OPTIONAL,
1600                    stime[4]              KerberosTime,
1601                    susec[5]              INTEGER,
1602                    error-code[6]         INTEGER,
1603                    crealm[7]             Realm OPTIONAL,
1604                    cname[8]              PrincipalName OPTIONAL,
1605                    realm[9]              Realm, -- Correct realm
1606                    sname[10]             PrincipalName, -- Correct name
1607                    e-text[11]            GeneralString OPTIONAL,
1608                    e-data[12]            OCTET STRING OPTIONAL
1609    }
1610
1611    e-data    This field contains additional data about the error for use
1612              by the application to help it recover from or handle the
1613              error.  If the errorcode is KDC_ERR_PREAUTH_REQUIRED, then
1614              the e-data field will contain an encoding of a sequence of
1615              padata fields, each corresponding to an acceptable pre-
1616              authentication method and optionally containing data for
1617              the method:
1618
1619       METHOD-DATA ::=    SEQUENCE of PA-DATA
1620
1621    If the error-code is KRB_AP_ERR_METHOD, then the e-data field will
1622    contain an encoding of the following sequence:
1623
1624       METHOD-DATA ::=    SEQUENCE {
1625                          method-type[0]   INTEGER,
1626                          method-data[1]   OCTET STRING OPTIONAL
1627       }
1628
1629       EncryptionKey ::=   SEQUENCE {
1630                          keytype[0]    INTEGER,
1631                          keyvalue[1]   OCTET STRING
1632       }
1633
1634       Checksum ::=   SEQUENCE {
1635                          cksumtype[0]   INTEGER,
1636                          checksum[1]    OCTET STRING
1637       }
1638
1639 */