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