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