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