private_data->fast_armor_ ...
[metze/wireshark/wip.git] / epan / dissectors / asn1 / kerberos / packet-kerberos-template.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  * Ronnie Sahlberg (C) 2004, major rewrite for new ASN.1/BER API.
9  *                           decryption of kerberos blobs if keytab is provided
10  *
11  * See RFC 1510, and various I-Ds and other documents showing additions,
12  * e.g. ones listed under
13  *
14  *      http://www.isi.edu/people/bcn/krb-revisions/
15  *
16  * and
17  *
18  *      http://www.ietf.org/internet-drafts/draft-ietf-krb-wg-kerberos-clarifications-07.txt
19  *
20  * and
21  *
22  *      http://www.ietf.org/internet-drafts/draft-ietf-krb-wg-kerberos-referrals-05.txt
23  *
24  * Some structures from RFC2630
25  *
26  * Wireshark - Network traffic analyzer
27  * By Gerald Combs <gerald@wireshark.org>
28  * Copyright 1998 Gerald Combs
29  *
30  * SPDX-License-Identifier: GPL-2.0-or-later
31  */
32
33 /*
34  * Some of the development of the Kerberos protocol decoder was sponsored by
35  * Cable Television Laboratories, Inc. ("CableLabs") based upon proprietary
36  * CableLabs' specifications. Your license and use of this protocol decoder
37  * does not mean that you are licensed to use the CableLabs'
38  * specifications.  If you have questions about this protocol, contact
39  * jf.mule [AT] cablelabs.com or c.stuart [AT] cablelabs.com for additional
40  * information.
41  */
42
43 #include <config.h>
44
45 #include <stdio.h>
46
47 #include <epan/packet.h>
48 #include <epan/exceptions.h>
49 #include <epan/strutil.h>
50 #include <epan/conversation.h>
51 #include <epan/asn1.h>
52 #include <epan/expert.h>
53 #include <epan/prefs.h>
54 #include <wsutil/wsgcrypt.h>
55 #include <wsutil/file_util.h>
56 #include <wsutil/str_util.h>
57 #include "packet-kerberos.h"
58 #include "packet-netbios.h"
59 #include "packet-tcp.h"
60 #include "packet-ber.h"
61 #include "packet-pkinit.h"
62 #include "packet-cms.h"
63 #include "packet-windows-common.h"
64
65 #include "read_keytab_file.h"
66
67 #include "packet-dcerpc-netlogon.h"
68 #include "packet-dcerpc.h"
69
70 #include "packet-gssapi.h"
71 #include "packet-smb-common.h"
72
73 #define KEY_USAGE_FAST_REQ_CHKSUM       50
74 #define KEY_USAGE_FAST_ENC              51
75 #define KEY_USAGE_FAST_REP              52
76 #define KEY_USAGE_FAST_FINISHED         53
77 #define KEY_USAGE_ENC_CHALLENGE_CLIENT  54
78 #define KEY_USAGE_ENC_CHALLENGE_KDC     55
79
80 void proto_register_kerberos(void);
81 void proto_reg_handoff_kerberos(void);
82
83 #define UDP_PORT_KERBEROS               88
84 #define TCP_PORT_KERBEROS               88
85
86 #define ADDRESS_STR_BUFSIZ 256
87
88 typedef struct kerberos_key {
89         guint32 keytype;
90         int keylength;
91         const guint8 *keyvalue;
92 } kerberos_key_t;
93
94 typedef struct {
95         gboolean kdc_response_initialized;
96         gboolean kdc_response;
97         guint32 etype;
98         guint32 padata_type;
99         guint32 enctype;
100         kerberos_key_t key;
101         guint32 ad_type;
102         guint32 addr_type;
103         guint32 checksum_type;
104         guint32 fast_type;
105         gboolean fast_armor_request;
106         gboolean fast_armor_within_enc_ticket_part;
107         gboolean fast_armor_ticket_sessionkey_needed;
108         const enc_key_t *fast_armor_ticket_sessionkey;
109         gboolean fast_armor_within_authenticator;
110         gboolean fast_armor_remote_subkey_needed;
111         const enc_key_t *fast_armor_remote_subkey;
112 } kerberos_private_data_t;
113
114 static dissector_handle_t kerberos_handle_udp;
115
116 /* Forward declarations */
117 static int dissect_kerberos_Applications(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
118 static int dissect_kerberos_PA_ENC_TIMESTAMP(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
119 static int dissect_kerberos_PA_ENC_TS_ENC(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
120 static int dissect_kerberos_KERB_PA_PAC_REQUEST(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
121 static int dissect_kerberos_PA_S4U2Self(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
122 static int dissect_kerberos_ETYPE_INFO(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
123 static int dissect_kerberos_ETYPE_INFO2(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
124 static int dissect_kerberos_AD_IF_RELEVANT(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
125 static int dissect_kerberos_PA_AUTHENTICATION_SET_ELEM(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
126 static int dissect_kerberos_PA_FX_FAST_REQUEST(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
127 static int dissect_kerberos_PA_FX_FAST_REPLY(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
128 static int dissect_kerberos_KrbFastReq(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
129 static int dissect_kerberos_KrbFastResponse(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
130 static int dissect_kerberos_EncryptedChallenge(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
131 static int dissect_kerberos_PA_SUPPORTED_ENCTYPES(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
132 static int dissect_kerberos_PA_PAC_OPTIONS(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
133 static int dissect_kerberos_KERB_AD_RESTRICTION_ENTRY(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
134 static int dissect_kerberos_AD_AP_OPTIONS(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
135 static int dissect_kerberos_Checksum(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
136
137 /* Desegment Kerberos over TCP messages */
138 static gboolean krb_desegment = TRUE;
139
140 static gint proto_kerberos = -1;
141
142 static gint hf_krb_rm_reserved = -1;
143 static gint hf_krb_rm_reclen = -1;
144 static gint hf_krb_provsrv_location = -1;
145 static gint hf_krb_smb_nt_status = -1;
146 static gint hf_krb_smb_unknown = -1;
147 static gint hf_krb_address_ip = -1;
148 static gint hf_krb_address_netbios = -1;
149 static gint hf_krb_address_ipv6 = -1;
150 static gint hf_krb_gssapi_len = -1;
151 static gint hf_krb_gssapi_bnd = -1;
152 static gint hf_krb_gssapi_dlgopt = -1;
153 static gint hf_krb_gssapi_dlglen = -1;
154 static gint hf_krb_gssapi_c_flag_deleg = -1;
155 static gint hf_krb_gssapi_c_flag_mutual = -1;
156 static gint hf_krb_gssapi_c_flag_replay = -1;
157 static gint hf_krb_gssapi_c_flag_sequence = -1;
158 static gint hf_krb_gssapi_c_flag_conf = -1;
159 static gint hf_krb_gssapi_c_flag_integ = -1;
160 static gint hf_krb_gssapi_c_flag_dce_style = -1;
161 static gint hf_krb_midl_version = -1;
162 static gint hf_krb_midl_hdr_len = -1;
163 static gint hf_krb_midl_fill_bytes = -1;
164 static gint hf_krb_midl_blob_len = -1;
165 static gint hf_krb_pac_signature_type = -1;
166 static gint hf_krb_pac_signature_signature = -1;
167 static gint hf_krb_w2k_pac_entries = -1;
168 static gint hf_krb_w2k_pac_version = -1;
169 static gint hf_krb_w2k_pac_type = -1;
170 static gint hf_krb_w2k_pac_size = -1;
171 static gint hf_krb_w2k_pac_offset = -1;
172 static gint hf_krb_pac_clientid = -1;
173 static gint hf_krb_pac_namelen = -1;
174 static gint hf_krb_pac_clientname = -1;
175 static gint hf_krb_pac_logon_info = -1;
176 static gint hf_krb_pac_credential_type = -1;
177 static gint hf_krb_pac_s4u_delegation_info = -1;
178 static gint hf_krb_pac_upn_dns_info = -1;
179 static gint hf_krb_pac_upn_flags = -1;
180 static gint hf_krb_pac_upn_dns_offset = -1;
181 static gint hf_krb_pac_upn_dns_len = -1;
182 static gint hf_krb_pac_upn_upn_offset = -1;
183 static gint hf_krb_pac_upn_upn_len = -1;
184 static gint hf_krb_pac_upn_upn_name = -1;
185 static gint hf_krb_pac_upn_dns_name = -1;
186 static gint hf_krb_pac_server_checksum = -1;
187 static gint hf_krb_pac_privsvr_checksum = -1;
188 static gint hf_krb_pac_client_info_type = -1;
189 static gint hf_krb_pa_supported_enctypes = -1;
190 static gint hf_krb_pa_supported_enctypes_des_cbc_crc = -1;
191 static gint hf_krb_pa_supported_enctypes_des_cbc_md5 = -1;
192 static gint hf_krb_pa_supported_enctypes_rc4_hmac = -1;
193 static gint hf_krb_pa_supported_enctypes_aes128_cts_hmac_sha1_96 = -1;
194 static gint hf_krb_pa_supported_enctypes_aes256_cts_hmac_sha1_96 = -1;
195 static gint hf_krb_pa_supported_enctypes_fast_supported = -1;
196 static gint hf_krb_pa_supported_enctypes_compound_identity_supported = -1;
197 static gint hf_krb_pa_supported_enctypes_claims_supported = -1;
198 static gint hf_krb_pa_supported_enctypes_resource_sid_compression_disabled = -1;
199 static gint hf_krb_ad_ap_options = -1;
200 static gint hf_krb_ad_ap_options_cbt = -1;
201 #include "packet-kerberos-hf.c"
202
203 /* Initialize the subtree pointers */
204 static gint ett_kerberos = -1;
205 static gint ett_krb_recordmark = -1;
206 static gint ett_krb_pac = -1;
207 static gint ett_krb_pac_drep = -1;
208 static gint ett_krb_pac_midl_blob = -1;
209 static gint ett_krb_pac_logon_info = -1;
210 static gint ett_krb_pac_s4u_delegation_info = -1;
211 static gint ett_krb_pac_upn_dns_info = -1;
212 static gint ett_krb_pac_server_checksum = -1;
213 static gint ett_krb_pac_privsvr_checksum = -1;
214 static gint ett_krb_pac_client_info_type = -1;
215 static gint ett_krb_pa_supported_enctypes = -1;
216 static gint ett_krb_ad_ap_options = -1;
217 #include "packet-kerberos-ett.c"
218
219 static expert_field ei_kerberos_decrypted_keytype = EI_INIT;
220 static expert_field ei_kerberos_address = EI_INIT;
221 static expert_field ei_krb_gssapi_dlglen = EI_INIT;
222
223 static dissector_handle_t krb4_handle=NULL;
224
225 /* Global variables */
226 static guint32 krb5_errorcode;
227 static guint32 gbl_keytype;
228 static gboolean gbl_do_col_info;
229
230 #include "packet-kerberos-val.h"
231
232 static void
233 call_kerberos_callbacks(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int tag, kerberos_callbacks *cb)
234 {
235         if(!cb){
236                 return;
237         }
238
239         while(cb->tag){
240                 if(cb->tag==tag){
241                         cb->callback(pinfo, tvb, tree);
242                         return;
243                 }
244                 cb++;
245         }
246         return;
247 }
248
249 static kerberos_private_data_t*
250 kerberos_get_private_data(asn1_ctx_t *actx)
251 {
252         if (!actx->private_data) {
253                 actx->private_data = wmem_new0(wmem_packet_scope(), kerberos_private_data_t);
254         }
255         return (kerberos_private_data_t *)(actx->private_data);
256 }
257
258 #ifdef HAVE_KERBEROS
259
260 /* Decrypt Kerberos blobs */
261 gboolean krb_decrypt = FALSE;
262
263 /* keytab filename */
264 static const char *keytab_filename = "";
265
266 void
267 read_keytab_file_from_preferences(void)
268 {
269         static char *last_keytab = NULL;
270
271         if (!krb_decrypt) {
272                 return;
273         }
274
275         if (keytab_filename == NULL) {
276                 return;
277         }
278
279         if (last_keytab && !strcmp(last_keytab, keytab_filename)) {
280                 return;
281         }
282
283         g_free(last_keytab);
284         last_keytab = g_strdup(keytab_filename);
285
286         read_keytab_file(last_keytab);
287 }
288 #endif /* HAVE_KERBEROS */
289
290 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
291 #ifdef _WIN32
292 /* prevent redefinition warnings in kfw-2.5\inc\win_mac.h */
293 #undef HAVE_GETADDRINFO
294 #undef HAVE_SYS_TYPES_H
295 #endif /* _WIN32 */
296 #include <krb5.h>
297 enc_key_t *enc_key_list=NULL;
298
299 static void
300 add_encryption_key(packet_info *pinfo, int keytype, int keylength, const char *keyvalue, const char *origin)
301 {
302         enc_key_t *new_key;
303
304         if(pinfo->fd->flags.visited){
305                 return;
306         }
307
308 printf("%d:%s:%s: added key in %u keytype:%d len:%d\n", __LINE__, G_STRFUNC, origin, pinfo->fd->num, keytype, keylength);
309         new_key=(enc_key_t *)g_malloc(sizeof(enc_key_t));
310         g_snprintf(new_key->key_origin, KRB_MAX_ORIG_LEN, "%s learnt from frame %u",origin,pinfo->num);
311         new_key->fd_num = pinfo->num;
312         new_key->next=enc_key_list;
313         enc_key_list=new_key;
314         new_key->keytype=keytype;
315         new_key->keylength=keylength;
316         /*XXX this needs to be freed later */
317         new_key->keyvalue=(char *)g_memdup(keyvalue, keylength);
318 }
319 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
320
321 #if defined(HAVE_MIT_KERBEROS)
322
323 static krb5_context krb5_ctx;
324
325 USES_APPLE_DEPRECATED_API
326 void
327 read_keytab_file(const char *filename)
328 {
329         krb5_keytab keytab;
330         krb5_error_code ret;
331         krb5_keytab_entry key;
332         krb5_kt_cursor cursor;
333         static gboolean first_time=TRUE;
334
335         if (filename == NULL || filename[0] == 0) {
336                 return;
337         }
338
339         if(first_time){
340                 first_time=FALSE;
341                 ret = krb5_init_context(&krb5_ctx);
342                 if(ret && ret != KRB5_CONFIG_CANTOPEN){
343                         return;
344                 }
345         }
346
347         /* should use a file in the wireshark users dir */
348         ret = krb5_kt_resolve(krb5_ctx, filename, &keytab);
349         if(ret){
350                 fprintf(stderr, "KERBEROS ERROR: Badly formatted keytab filename :%s\n",filename);
351
352                 return;
353         }
354
355         ret = krb5_kt_start_seq_get(krb5_ctx, keytab, &cursor);
356         if(ret){
357                 fprintf(stderr, "KERBEROS ERROR: Could not open or could not read from keytab file :%s\n",filename);
358                 return;
359         }
360
361         do{
362                 ret = krb5_kt_next_entry(krb5_ctx, keytab, &key, &cursor);
363                 if(ret==0){
364                         enc_key_t *new_key;
365                         int i;
366                         char *pos;
367
368                         new_key = g_new(enc_key_t, 1);
369                         new_key->fd_num = -1;
370                         new_key->next = enc_key_list;
371
372                         /* generate origin string, describing where this key came from */
373                         pos=new_key->key_origin;
374                         pos+=MIN(KRB_MAX_ORIG_LEN,
375                                          g_snprintf(pos, KRB_MAX_ORIG_LEN, "keytab principal "));
376                         for(i=0;i<key.principal->length;i++){
377                                 pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
378                                                  g_snprintf(pos, (gulong)(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin)), "%s%s",(i?"/":""),(key.principal->data[i]).data));
379                         }
380                         pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
381                                          g_snprintf(pos, (gulong)(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin)), "@%s",key.principal->realm.data));
382                         *pos=0;
383                         new_key->keytype=key.key.enctype;
384                         new_key->keylength=key.key.length;
385                         new_key->keyvalue=(char *)g_memdup(key.key.contents, key.key.length);
386                         enc_key_list=new_key;
387                         ret = krb5_free_keytab_entry_contents(krb5_ctx, &key);
388                         if (ret) {
389                                 fprintf(stderr, "KERBEROS ERROR: Could not release the entry: %d", ret);
390                                 ret = 0; /* try to continue with the next entry */
391                         }
392                 }
393         }while(ret==0);
394
395         ret = krb5_kt_end_seq_get(krb5_ctx, keytab, &cursor);
396         if(ret){
397                 fprintf(stderr, "KERBEROS ERROR: Could not release the keytab cursor: %d", ret);
398         }
399         ret = krb5_kt_close(krb5_ctx, keytab);
400         if(ret){
401                 fprintf(stderr, "KERBEROS ERROR: Could not close the key table handle: %d", ret);
402         }
403 }
404
405
406 guint8 *
407 decrypt_krb5_data(proto_tree *tree _U_, packet_info *pinfo,
408                                         int usage,
409                                         tvbuff_t *cryptotvb,
410                                         int keytype,
411                                         int *datalen)
412 {
413         krb5_error_code ret;
414         enc_key_t *ek;
415         krb5_data data = {0,0,NULL};
416         krb5_keytab_entry key;
417         int length = tvb_captured_length(cryptotvb);
418         const guint8 *cryptotext = tvb_get_ptr(cryptotvb, 0, length);
419
420         /* don't do anything if we are not attempting to decrypt data */
421         if(!krb_decrypt || length < 1){
422                 return NULL;
423         }
424
425         /* make sure we have all the data we need */
426         if (tvb_captured_length(cryptotvb) < tvb_reported_length(cryptotvb)) {
427                 return NULL;
428         }
429
430         read_keytab_file_from_preferences();
431         data.data = (char *)wmem_alloc(pinfo->pool, length);
432         data.length = length;
433
434         for(ek=enc_key_list;ek;ek=ek->next){
435                 krb5_enc_data input;
436
437                 /* shortcircuit and bail out if enctypes are not matching */
438                 if((keytype != -1) && (ek->keytype != keytype)) {
439                         continue;
440                 }
441
442                 input.enctype = ek->keytype;
443                 input.ciphertext.length = length;
444                 input.ciphertext.data = (guint8 *)cryptotext;
445
446                 key.key.enctype=ek->keytype;
447                 key.key.length=ek->keylength;
448                 key.key.contents=ek->keyvalue;
449                 ret = krb5_c_decrypt(krb5_ctx, &(key.key), usage, 0, &input, &data);
450                 if(ret == 0){
451                         char *user_data;
452
453 printf("%d:%s:%s: woohoo decrypted keytype:%d in frame:%u\n", __LINE__, G_STRFUNC, ek->key_origin, ek->keytype, pinfo->fd->num);
454                         expert_add_info_format(pinfo, NULL, &ei_kerberos_decrypted_keytype,
455                                                                    "Decrypted keytype %d in frame %u using %s",
456                                                                    ek->keytype, pinfo->num, ek->key_origin);
457
458                         proto_tree_add_text(tree, NULL, 0, 0, "[Decrypted using: %s]", ek->key_origin);
459
460                         user_data=data.data;
461                         if (datalen) {
462                                 *datalen = data.length;
463                         }
464                         return user_data;
465                 }
466         }
467
468         return NULL;
469 }
470 USES_APPLE_RST
471
472 #elif defined(HAVE_HEIMDAL_KERBEROS)
473 static krb5_context krb5_ctx;
474
475 USES_APPLE_DEPRECATED_API
476 void
477 read_keytab_file(const char *filename)
478 {
479         krb5_keytab keytab;
480         krb5_error_code ret;
481         krb5_keytab_entry key;
482         krb5_kt_cursor cursor;
483         enc_key_t *new_key;
484         static gboolean first_time=TRUE;
485
486         if (filename == NULL || filename[0] == 0) {
487                 return;
488         }
489
490         if(first_time){
491                 first_time=FALSE;
492                 ret = krb5_init_context(&krb5_ctx);
493                 if(ret){
494                         return;
495                 }
496         }
497
498         /* should use a file in the wireshark users dir */
499         ret = krb5_kt_resolve(krb5_ctx, filename, &keytab);
500         if(ret){
501                 fprintf(stderr, "KERBEROS ERROR: Could not open keytab file :%s\n",filename);
502
503                 return;
504         }
505
506         ret = krb5_kt_start_seq_get(krb5_ctx, keytab, &cursor);
507         if(ret){
508                 fprintf(stderr, "KERBEROS ERROR: Could not read from keytab file :%s\n",filename);
509                 return;
510         }
511
512         do{
513                 ret = krb5_kt_next_entry(krb5_ctx, keytab, &key, &cursor);
514                 if(ret==0){
515                         unsigned int i;
516                         char *pos;
517
518                         new_key = g_new0(enc_key_t, 1);
519                         new_key->fd_num = -1;
520                         new_key->next = enc_key_list;
521
522                         /* generate origin string, describing where this key came from */
523                         pos=new_key->key_origin;
524                         pos+=MIN(KRB_MAX_ORIG_LEN,
525                                          g_snprintf(pos, KRB_MAX_ORIG_LEN, "keytab principal "));
526                         for(i=0;i<key.principal->name.name_string.len;i++){
527                                 pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
528                                                  g_snprintf(pos, KRB_MAX_ORIG_LEN-(pos-new_key->key_origin), "%s%s",(i?"/":""),key.principal->name.name_string.val[i]));
529                         }
530                         pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
531                                          g_snprintf(pos, KRB_MAX_ORIG_LEN-(pos-new_key->key_origin), "@%s",key.principal->realm));
532                         *pos=0;
533                         new_key->keytype=key.keyblock.keytype;
534                         new_key->keylength=(int)key.keyblock.keyvalue.length;
535                         new_key->keyvalue = (guint8 *)g_memdup(key.keyblock.keyvalue.data, (guint)key.keyblock.keyvalue.length);
536                         enc_key_list=new_key;
537                         ret = krb5_kt_free_entry(krb5_ctx, &key);
538                         if (ret) {
539                                 fprintf(stderr, "KERBEROS ERROR: Could not release the entry: %d", ret);
540                                 ret = 0; /* try to continue with the next entry */
541                         }
542                 }
543         }while(ret==0);
544
545         ret = krb5_kt_end_seq_get(krb5_ctx, keytab, &cursor);
546         if(ret){
547                 fprintf(stderr, "KERBEROS ERROR: Could not release the keytab cursor: %d", ret);
548         }
549         ret = krb5_kt_close(krb5_ctx, keytab);
550         if(ret){
551                 fprintf(stderr, "KERBEROS ERROR: Could not close the key table handle: %d", ret);
552         }
553
554 }
555 USES_APPLE_RST
556
557
558 guint8 *
559 decrypt_krb5_data(proto_tree *tree _U_, packet_info *pinfo,
560                                         int usage,
561                                         tvbuff_t *cryptotvb,
562                                         int keytype,
563                                         int *datalen)
564 {
565         krb5_error_code ret;
566         krb5_data data;
567         enc_key_t *ek;
568         int length = tvb_captured_length(cryptotvb);
569         const guint8 *cryptotext = tvb_get_ptr(cryptotvb, 0, length);
570
571         /* don't do anything if we are not attempting to decrypt data */
572         if(!krb_decrypt){
573                 return NULL;
574         }
575
576         /* make sure we have all the data we need */
577         if (tvb_captured_length(cryptotvb) < tvb_reported_length(cryptotvb)) {
578                 return NULL;
579         }
580
581         read_keytab_file_from_preferences();
582
583         for(ek=enc_key_list;ek;ek=ek->next){
584                 krb5_keytab_entry key;
585                 krb5_crypto crypto;
586                 guint8 *cryptocopy; /* workaround for pre-0.6.1 heimdal bug */
587
588                 /* shortcircuit and bail out if enctypes are not matching */
589                 if((keytype != -1) && (ek->keytype != keytype)) {
590                         continue;
591                 }
592
593                 key.keyblock.keytype=ek->keytype;
594                 key.keyblock.keyvalue.length=ek->keylength;
595                 key.keyblock.keyvalue.data=ek->keyvalue;
596                 ret = krb5_crypto_init(krb5_ctx, &(key.keyblock), (krb5_enctype)ENCTYPE_NULL, &crypto);
597                 if(ret){
598                         return NULL;
599                 }
600
601                 /* pre-0.6.1 versions of Heimdal would sometimes change
602                    the cryptotext data even when the decryption failed.
603                    This would obviously not work since we iterate over the
604                    keys. So just give it a copy of the crypto data instead.
605                    This has been seen for RC4-HMAC blobs.
606                 */
607                 cryptocopy = (guint8 *)wmem_memdup(wmem_packet_scope(), cryptotext, length);
608                 ret = krb5_decrypt_ivec(krb5_ctx, crypto, usage,
609                                                                 cryptocopy, length,
610                                                                 &data,
611                                                                 NULL);
612                 if((ret == 0) && (length>0)){
613                         char *user_data;
614
615 printf("%d:%s:%s: woohoo decrypted keytype:%d in frame:%u\n", __LINE__, G_STRFUNC, ek->key_origin, ek->keytype, pinfo->fd->num);
616                         expert_add_info_format(pinfo, NULL, &ei_kerberos_decrypted_keytype,
617                                                                    "Decrypted keytype %d in frame %u using %s",
618                                                                    ek->keytype, pinfo->num, ek->key_origin);
619
620                         proto_tree_add_text(tree, NULL, 0, 0, "[Decrypted using: %s]", ek->key_origin);
621
622                         krb5_crypto_destroy(krb5_ctx, crypto);
623                         /* return a private wmem_alloced blob to the caller */
624                         user_data = (char *)wmem_memdup(pinfo->pool, data.data, (guint)data.length);
625                         if (datalen) {
626                                 *datalen = (int)data.length;
627                         }
628                         return user_data;
629                 }
630                 krb5_crypto_destroy(krb5_ctx, crypto);
631         }
632         return NULL;
633 }
634
635 #elif defined (HAVE_LIBNETTLE)
636
637 #define SERVICE_KEY_SIZE (DES3_KEY_SIZE + 2)
638 #define KEYTYPE_DES3_CBC_MD5 5  /* Currently the only one supported */
639
640 typedef struct _service_key_t {
641         guint16 kvno;
642         int     keytype;
643         int     length;
644         guint8 *contents;
645         char    origin[KRB_MAX_ORIG_LEN+1];
646 } service_key_t;
647 GSList *service_key_list = NULL;
648
649
650 static void
651 add_encryption_key(packet_info *pinfo, int keytype, int keylength, const char *keyvalue, const char *origin)
652 {
653         service_key_t *new_key;
654
655         if(pinfo->fd->flags.visited){
656                 return;
657         }
658
659 printf("%d:%s:%s: added key in %u keytype:%d len:%d\n", __LINE__, G_STRFUNC, origin, pinfo->fd->num, keytype, keylength);
660
661         new_key = g_malloc(sizeof(service_key_t));
662         new_key->kvno = 0;
663         new_key->keytype = keytype;
664         new_key->length = keylength;
665         new_key->contents = g_memdup(keyvalue, keylength);
666         g_snprintf(new_key->origin, KRB_MAX_ORIG_LEN, "%s learnt from frame %u", origin, pinfo->num);
667         service_key_list = g_slist_append(service_key_list, (gpointer) new_key);
668 }
669
670 static void
671 clear_keytab(void) {
672         GSList *ske;
673         service_key_t *sk;
674
675         for(ske = service_key_list; ske != NULL; ske = g_slist_next(ske)){
676                 sk = (service_key_t *) ske->data;
677                 if (sk) {
678                         g_free(sk->contents);
679                         g_free(sk);
680                 }
681         }
682         g_slist_free(service_key_list);
683         service_key_list = NULL;
684 }
685
686 static void
687 read_keytab_file(const char *service_key_file)
688 {
689         FILE *skf;
690         ws_statb64 st;
691         service_key_t *sk;
692         unsigned char buf[SERVICE_KEY_SIZE];
693         int newline_skip = 0, count = 0;
694
695         if (service_key_file != NULL && ws_stat64 (service_key_file, &st) == 0) {
696
697                 /* The service key file contains raw 192-bit (24 byte) 3DES keys.
698                  * There can be zero, one (\n), or two (\r\n) characters between
699                  * keys.  Trailing characters are ignored.
700                  */
701
702                 /* XXX We should support the standard keytab format instead */
703                 if (st.st_size > SERVICE_KEY_SIZE) {
704                         if ( (st.st_size % (SERVICE_KEY_SIZE + 1) == 0) ||
705                                  (st.st_size % (SERVICE_KEY_SIZE + 1) == SERVICE_KEY_SIZE) ) {
706                                 newline_skip = 1;
707                         } else if ( (st.st_size % (SERVICE_KEY_SIZE + 2) == 0) ||
708                                  (st.st_size % (SERVICE_KEY_SIZE + 2) == SERVICE_KEY_SIZE) ) {
709                                 newline_skip = 2;
710                         }
711                 }
712
713                 skf = ws_fopen(service_key_file, "rb");
714                 if (! skf) return;
715
716                 while (fread(buf, SERVICE_KEY_SIZE, 1, skf) == 1) {
717                         sk = g_malloc(sizeof(service_key_t));
718                         sk->kvno = buf[0] << 8 | buf[1];
719                         sk->keytype = KEYTYPE_DES3_CBC_MD5;
720                         sk->length = DES3_KEY_SIZE;
721                         sk->contents = g_memdup(buf + 2, DES3_KEY_SIZE);
722                         g_snprintf(sk->origin, KRB_MAX_ORIG_LEN, "3DES service key file, key #%d, offset %ld", count, ftell(skf));
723                         service_key_list = g_slist_append(service_key_list, (gpointer) sk);
724                         if (fseek(skf, newline_skip, SEEK_CUR) < 0) {
725                                 fprintf(stderr, "unable to seek...\n");
726                                 return;
727                         }
728                         count++;
729                 }
730                 fclose(skf);
731         }
732 }
733
734 #define CONFOUNDER_PLUS_CHECKSUM 24
735
736 guint8 *
737 decrypt_krb5_data(proto_tree *tree, packet_info *pinfo,
738                                         int _U_ usage,
739                                         tvbuff_t *cryptotvb,
740                                         int keytype,
741                                         int *datalen)
742 {
743         tvbuff_t *encr_tvb;
744         guint8 *decrypted_data = NULL, *plaintext = NULL;
745         guint8 cls;
746         gboolean pc;
747         guint32 tag, item_len, data_len;
748         int id_offset, offset;
749         guint8 key[DES3_KEY_SIZE];
750         guint8 initial_vector[DES_BLOCK_SIZE];
751         gcry_md_hd_t md5_handle;
752         guint8 *digest;
753         guint8 zero_fill[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
754         guint8 confounder[8];
755         gboolean ind;
756         GSList *ske;
757         service_key_t *sk;
758         struct des3_ctx ctx;
759         int length = tvb_captured_length(cryptotvb);
760         const guint8 *cryptotext = tvb_get_ptr(cryptotvb, 0, length);
761
762
763         /* don't do anything if we are not attempting to decrypt data */
764         if(!krb_decrypt){
765                 return NULL;
766         }
767
768         /* make sure we have all the data we need */
769         if (tvb_captured_length(cryptotvb) < tvb_reported_length(cryptotvb)) {
770                 return NULL;
771         }
772
773         if (keytype != KEYTYPE_DES3_CBC_MD5 || service_key_list == NULL) {
774                 return NULL;
775         }
776
777         decrypted_data = wmem_alloc(wmem_packet_scope(), length);
778         for(ske = service_key_list; ske != NULL; ske = g_slist_next(ske)){
779                 gboolean do_continue = FALSE;
780                 gboolean digest_ok;
781                 sk = (service_key_t *) ske->data;
782
783                 des_fix_parity(DES3_KEY_SIZE, key, sk->contents);
784
785                 memset(initial_vector, 0, DES_BLOCK_SIZE);
786                 des3_set_key(&ctx, key);
787                 cbc_decrypt(&ctx, des3_decrypt, DES_BLOCK_SIZE, initial_vector,
788                                         length, decrypted_data, cryptotext);
789                 encr_tvb = tvb_new_real_data(decrypted_data, length, length);
790
791                 tvb_memcpy(encr_tvb, confounder, 0, 8);
792
793                 /* We have to pull the decrypted data length from the decrypted
794                  * content.  If the key doesn't match or we otherwise get garbage,
795                  * an exception may get thrown while decoding the ASN.1 header.
796                  * Catch it, just in case.
797                  */
798                 TRY {
799                         id_offset = get_ber_identifier(encr_tvb, CONFOUNDER_PLUS_CHECKSUM, &cls, &pc, &tag);
800                         offset = get_ber_length(encr_tvb, id_offset, &item_len, &ind);
801                 }
802                 CATCH_BOUNDS_ERRORS {
803                         tvb_free(encr_tvb);
804                         do_continue = TRUE;
805                 }
806                 ENDTRY;
807
808                 if (do_continue) continue;
809
810                 data_len = item_len + offset - CONFOUNDER_PLUS_CHECKSUM;
811                 if ((int) item_len + offset > length) {
812                         tvb_free(encr_tvb);
813                         continue;
814                 }
815
816                 if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
817                         return NULL;
818                 }
819                 gcry_md_write(md5_handle, confounder, 8);
820                 gcry_md_write(md5_handle, zero_fill, 16);
821                 gcry_md_write(md5_handle, decrypted_data + CONFOUNDER_PLUS_CHECKSUM, data_len);
822                 digest = gcry_md_read(md5_handle, 0);
823
824                 digest_ok = (tvb_memeql (encr_tvb, 8, digest, HASH_MD5_LENGTH) == 0);
825                 gcry_md_close(md5_handle);
826                 if (digest_ok) {
827                         plaintext = (guint8* )tvb_memdup(pinfo->pool, encr_tvb, CONFOUNDER_PLUS_CHECKSUM, data_len);
828                         tvb_free(encr_tvb);
829
830                         if (datalen) {
831                                 *datalen = data_len;
832                         }
833                         return(plaintext);
834                 }
835                 tvb_free(encr_tvb);
836         }
837
838         return NULL;
839 }
840
841 #endif  /* HAVE_MIT_KERBEROS / HAVE_HEIMDAL_KERBEROS / HAVE_LIBNETTLE */
842
843 #define INET6_ADDRLEN   16
844
845 /* TCP Record Mark */
846 #define KRB_RM_RESERVED 0x80000000U
847 #define KRB_RM_RECLEN   0x7fffffffU
848
849 #define KRB5_MSG_TICKET                 1       /* Ticket */
850 #define KRB5_MSG_AUTHENTICATOR          2       /* Authenticator */
851 #define KRB5_MSG_ENC_TICKET_PART        3       /* EncTicketPart */
852 #define KRB5_MSG_AS_REQ                 10      /* AS-REQ type */
853 #define KRB5_MSG_AS_REP                 11      /* AS-REP type */
854 #define KRB5_MSG_TGS_REQ                12      /* TGS-REQ type */
855 #define KRB5_MSG_TGS_REP                13      /* TGS-REP type */
856 #define KRB5_MSG_AP_REQ                 14      /* AP-REQ type */
857 #define KRB5_MSG_AP_REP                 15      /* AP-REP type */
858
859 #define KRB5_MSG_SAFE                   20      /* KRB-SAFE type */
860 #define KRB5_MSG_PRIV                   21      /* KRB-PRIV type */
861 #define KRB5_MSG_CRED                   22      /* KRB-CRED type */
862 #define KRB5_MSG_ENC_AS_REP_PART        25      /* EncASRepPart */
863 #define KRB5_MSG_ENC_TGS_REP_PART       26      /* EncTGSRepPart */
864 #define KRB5_MSG_ENC_AP_REP_PART        27      /* EncAPRepPart */
865 #define KRB5_MSG_ENC_KRB_PRIV_PART      28      /* EncKrbPrivPart */
866 #define KRB5_MSG_ENC_KRB_CRED_PART      29      /* EncKrbCredPart */
867 #define KRB5_MSG_ERROR                  30      /* KRB-ERROR type */
868
869 #define KRB5_CHKSUM_GSSAPI              0x8003
870 /*
871  * For KERB_ENCTYPE_RC4_HMAC and KERB_ENCTYPE_RC4_HMAC_EXP, see
872  *
873  *      http://www.ietf.org/internet-drafts/draft-brezak-win2k-krb-rc4-hmac-04.txt
874  *
875  * unless it's expired.
876  */
877
878 /* Principal name-type */
879 #define KRB5_NT_UNKNOWN         0
880 #define KRB5_NT_PRINCIPAL       1
881 #define KRB5_NT_SRV_INST        2
882 #define KRB5_NT_SRV_HST         3
883 #define KRB5_NT_SRV_XHST        4
884 #define KRB5_NT_UID             5
885 #define KRB5_NT_X500_PRINCIPAL  6
886 #define KRB5_NT_SMTP_NAME       7
887 #define KRB5_NT_ENTERPRISE      10
888
889 /*
890  * MS specific name types, from
891  *
892  *      http://msdn.microsoft.com/library/en-us/security/security/kerb_external_name.asp
893  */
894 #define KRB5_NT_MS_PRINCIPAL            -128
895 #define KRB5_NT_MS_PRINCIPAL_AND_SID    -129
896 #define KRB5_NT_ENT_PRINCIPAL_AND_SID   -130
897 #define KRB5_NT_PRINCIPAL_AND_SID       -131
898 #define KRB5_NT_SRV_INST_AND_SID        -132
899
900 /* error table constants */
901 /* I prefixed the krb5_err.et constant names with KRB5_ET_ for these */
902 #define KRB5_ET_KRB5KDC_ERR_NONE                        0
903 #define KRB5_ET_KRB5KDC_ERR_NAME_EXP                    1
904 #define KRB5_ET_KRB5KDC_ERR_SERVICE_EXP                 2
905 #define KRB5_ET_KRB5KDC_ERR_BAD_PVNO                    3
906 #define KRB5_ET_KRB5KDC_ERR_C_OLD_MAST_KVNO             4
907 #define KRB5_ET_KRB5KDC_ERR_S_OLD_MAST_KVNO             5
908 #define KRB5_ET_KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN         6
909 #define KRB5_ET_KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN         7
910 #define KRB5_ET_KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE        8
911 #define KRB5_ET_KRB5KDC_ERR_NULL_KEY                    9
912 #define KRB5_ET_KRB5KDC_ERR_CANNOT_POSTDATE             10
913 #define KRB5_ET_KRB5KDC_ERR_NEVER_VALID                 11
914 #define KRB5_ET_KRB5KDC_ERR_POLICY                      12
915 #define KRB5_ET_KRB5KDC_ERR_BADOPTION                   13
916 #define KRB5_ET_KRB5KDC_ERR_ETYPE_NOSUPP                14
917 #define KRB5_ET_KRB5KDC_ERR_SUMTYPE_NOSUPP              15
918 #define KRB5_ET_KRB5KDC_ERR_PADATA_TYPE_NOSUPP          16
919 #define KRB5_ET_KRB5KDC_ERR_TRTYPE_NOSUPP               17
920 #define KRB5_ET_KRB5KDC_ERR_CLIENT_REVOKED              18
921 #define KRB5_ET_KRB5KDC_ERR_SERVICE_REVOKED             19
922 #define KRB5_ET_KRB5KDC_ERR_TGT_REVOKED                 20
923 #define KRB5_ET_KRB5KDC_ERR_CLIENT_NOTYET               21
924 #define KRB5_ET_KRB5KDC_ERR_SERVICE_NOTYET              22
925 #define KRB5_ET_KRB5KDC_ERR_KEY_EXP                     23
926 #define KRB5_ET_KRB5KDC_ERR_PREAUTH_FAILED              24
927 #define KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED            25
928 #define KRB5_ET_KRB5KDC_ERR_SERVER_NOMATCH              26
929 #define KRB5_ET_KRB5KDC_ERR_MUST_USE_USER2USER          27
930 #define KRB5_ET_KRB5KDC_ERR_PATH_NOT_ACCEPTED           28
931 #define KRB5_ET_KRB5KDC_ERR_SVC_UNAVAILABLE             29
932 #define KRB5_ET_KRB5KRB_AP_ERR_BAD_INTEGRITY            31
933 #define KRB5_ET_KRB5KRB_AP_ERR_TKT_EXPIRED              32
934 #define KRB5_ET_KRB5KRB_AP_ERR_TKT_NYV                  33
935 #define KRB5_ET_KRB5KRB_AP_ERR_REPEAT                   34
936 #define KRB5_ET_KRB5KRB_AP_ERR_NOT_US                   35
937 #define KRB5_ET_KRB5KRB_AP_ERR_BADMATCH                 36
938 #define KRB5_ET_KRB5KRB_AP_ERR_SKEW                     37
939 #define KRB5_ET_KRB5KRB_AP_ERR_BADADDR                  38
940 #define KRB5_ET_KRB5KRB_AP_ERR_BADVERSION               39
941 #define KRB5_ET_KRB5KRB_AP_ERR_MSG_TYPE                 40
942 #define KRB5_ET_KRB5KRB_AP_ERR_MODIFIED                 41
943 #define KRB5_ET_KRB5KRB_AP_ERR_BADORDER                 42
944 #define KRB5_ET_KRB5KRB_AP_ERR_ILL_CR_TKT               43
945 #define KRB5_ET_KRB5KRB_AP_ERR_BADKEYVER                44
946 #define KRB5_ET_KRB5KRB_AP_ERR_NOKEY                    45
947 #define KRB5_ET_KRB5KRB_AP_ERR_MUT_FAIL                 46
948 #define KRB5_ET_KRB5KRB_AP_ERR_BADDIRECTION             47
949 #define KRB5_ET_KRB5KRB_AP_ERR_METHOD                   48
950 #define KRB5_ET_KRB5KRB_AP_ERR_BADSEQ                   49
951 #define KRB5_ET_KRB5KRB_AP_ERR_INAPP_CKSUM              50
952 #define KRB5_ET_KRB5KDC_AP_PATH_NOT_ACCEPTED            51
953 #define KRB5_ET_KRB5KRB_ERR_RESPONSE_TOO_BIG            52
954 #define KRB5_ET_KRB5KRB_ERR_GENERIC                     60
955 #define KRB5_ET_KRB5KRB_ERR_FIELD_TOOLONG               61
956 #define KRB5_ET_KDC_ERROR_CLIENT_NOT_TRUSTED            62
957 #define KRB5_ET_KDC_ERROR_KDC_NOT_TRUSTED               63
958 #define KRB5_ET_KDC_ERROR_INVALID_SIG                   64
959 #define KRB5_ET_KDC_ERR_KEY_TOO_WEAK                    65
960 #define KRB5_ET_KDC_ERR_CERTIFICATE_MISMATCH            66
961 #define KRB5_ET_KRB_AP_ERR_NO_TGT                       67
962 #define KRB5_ET_KDC_ERR_WRONG_REALM                     68
963 #define KRB5_ET_KRB_AP_ERR_USER_TO_USER_REQUIRED        69
964 #define KRB5_ET_KDC_ERR_CANT_VERIFY_CERTIFICATE         70
965 #define KRB5_ET_KDC_ERR_INVALID_CERTIFICATE             71
966 #define KRB5_ET_KDC_ERR_REVOKED_CERTIFICATE             72
967 #define KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNKNOWN       73
968 #define KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNAVAILABLE   74
969 #define KRB5_ET_KDC_ERR_CLIENT_NAME_MISMATCH            75
970 #define KRB5_ET_KDC_ERR_KDC_NAME_MISMATCH               76
971
972 static const value_string krb5_error_codes[] = {
973         { KRB5_ET_KRB5KDC_ERR_NONE, "KRB5KDC_ERR_NONE" },
974         { KRB5_ET_KRB5KDC_ERR_NAME_EXP, "KRB5KDC_ERR_NAME_EXP" },
975         { KRB5_ET_KRB5KDC_ERR_SERVICE_EXP, "KRB5KDC_ERR_SERVICE_EXP" },
976         { KRB5_ET_KRB5KDC_ERR_BAD_PVNO, "KRB5KDC_ERR_BAD_PVNO" },
977         { KRB5_ET_KRB5KDC_ERR_C_OLD_MAST_KVNO, "KRB5KDC_ERR_C_OLD_MAST_KVNO" },
978         { KRB5_ET_KRB5KDC_ERR_S_OLD_MAST_KVNO, "KRB5KDC_ERR_S_OLD_MAST_KVNO" },
979         { KRB5_ET_KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, "KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN" },
980         { KRB5_ET_KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, "KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN" },
981         { KRB5_ET_KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE, "KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE" },
982         { KRB5_ET_KRB5KDC_ERR_NULL_KEY, "KRB5KDC_ERR_NULL_KEY" },
983         { KRB5_ET_KRB5KDC_ERR_CANNOT_POSTDATE, "KRB5KDC_ERR_CANNOT_POSTDATE" },
984         { KRB5_ET_KRB5KDC_ERR_NEVER_VALID, "KRB5KDC_ERR_NEVER_VALID" },
985         { KRB5_ET_KRB5KDC_ERR_POLICY, "KRB5KDC_ERR_POLICY" },
986         { KRB5_ET_KRB5KDC_ERR_BADOPTION, "KRB5KDC_ERR_BADOPTION" },
987         { KRB5_ET_KRB5KDC_ERR_ETYPE_NOSUPP, "KRB5KDC_ERR_ETYPE_NOSUPP" },
988         { KRB5_ET_KRB5KDC_ERR_SUMTYPE_NOSUPP, "KRB5KDC_ERR_SUMTYPE_NOSUPP" },
989         { KRB5_ET_KRB5KDC_ERR_PADATA_TYPE_NOSUPP, "KRB5KDC_ERR_PADATA_TYPE_NOSUPP" },
990         { KRB5_ET_KRB5KDC_ERR_TRTYPE_NOSUPP, "KRB5KDC_ERR_TRTYPE_NOSUPP" },
991         { KRB5_ET_KRB5KDC_ERR_CLIENT_REVOKED, "KRB5KDC_ERR_CLIENT_REVOKED" },
992         { KRB5_ET_KRB5KDC_ERR_SERVICE_REVOKED, "KRB5KDC_ERR_SERVICE_REVOKED" },
993         { KRB5_ET_KRB5KDC_ERR_TGT_REVOKED, "KRB5KDC_ERR_TGT_REVOKED" },
994         { KRB5_ET_KRB5KDC_ERR_CLIENT_NOTYET, "KRB5KDC_ERR_CLIENT_NOTYET" },
995         { KRB5_ET_KRB5KDC_ERR_SERVICE_NOTYET, "KRB5KDC_ERR_SERVICE_NOTYET" },
996         { KRB5_ET_KRB5KDC_ERR_KEY_EXP, "KRB5KDC_ERR_KEY_EXP" },
997         { KRB5_ET_KRB5KDC_ERR_PREAUTH_FAILED, "KRB5KDC_ERR_PREAUTH_FAILED" },
998         { KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED, "KRB5KDC_ERR_PREAUTH_REQUIRED" },
999         { KRB5_ET_KRB5KDC_ERR_SERVER_NOMATCH, "KRB5KDC_ERR_SERVER_NOMATCH" },
1000         { KRB5_ET_KRB5KDC_ERR_MUST_USE_USER2USER, "KRB5KDC_ERR_MUST_USE_USER2USER" },
1001         { KRB5_ET_KRB5KDC_ERR_PATH_NOT_ACCEPTED, "KRB5KDC_ERR_PATH_NOT_ACCEPTED" },
1002         { KRB5_ET_KRB5KDC_ERR_SVC_UNAVAILABLE, "KRB5KDC_ERR_SVC_UNAVAILABLE" },
1003         { KRB5_ET_KRB5KRB_AP_ERR_BAD_INTEGRITY, "KRB5KRB_AP_ERR_BAD_INTEGRITY" },
1004         { KRB5_ET_KRB5KRB_AP_ERR_TKT_EXPIRED, "KRB5KRB_AP_ERR_TKT_EXPIRED" },
1005         { KRB5_ET_KRB5KRB_AP_ERR_TKT_NYV, "KRB5KRB_AP_ERR_TKT_NYV" },
1006         { KRB5_ET_KRB5KRB_AP_ERR_REPEAT, "KRB5KRB_AP_ERR_REPEAT" },
1007         { KRB5_ET_KRB5KRB_AP_ERR_NOT_US, "KRB5KRB_AP_ERR_NOT_US" },
1008         { KRB5_ET_KRB5KRB_AP_ERR_BADMATCH, "KRB5KRB_AP_ERR_BADMATCH" },
1009         { KRB5_ET_KRB5KRB_AP_ERR_SKEW, "KRB5KRB_AP_ERR_SKEW" },
1010         { KRB5_ET_KRB5KRB_AP_ERR_BADADDR, "KRB5KRB_AP_ERR_BADADDR" },
1011         { KRB5_ET_KRB5KRB_AP_ERR_BADVERSION, "KRB5KRB_AP_ERR_BADVERSION" },
1012         { KRB5_ET_KRB5KRB_AP_ERR_MSG_TYPE, "KRB5KRB_AP_ERR_MSG_TYPE" },
1013         { KRB5_ET_KRB5KRB_AP_ERR_MODIFIED, "KRB5KRB_AP_ERR_MODIFIED" },
1014         { KRB5_ET_KRB5KRB_AP_ERR_BADORDER, "KRB5KRB_AP_ERR_BADORDER" },
1015         { KRB5_ET_KRB5KRB_AP_ERR_ILL_CR_TKT, "KRB5KRB_AP_ERR_ILL_CR_TKT" },
1016         { KRB5_ET_KRB5KRB_AP_ERR_BADKEYVER, "KRB5KRB_AP_ERR_BADKEYVER" },
1017         { KRB5_ET_KRB5KRB_AP_ERR_NOKEY, "KRB5KRB_AP_ERR_NOKEY" },
1018         { KRB5_ET_KRB5KRB_AP_ERR_MUT_FAIL, "KRB5KRB_AP_ERR_MUT_FAIL" },
1019         { KRB5_ET_KRB5KRB_AP_ERR_BADDIRECTION, "KRB5KRB_AP_ERR_BADDIRECTION" },
1020         { KRB5_ET_KRB5KRB_AP_ERR_METHOD, "KRB5KRB_AP_ERR_METHOD" },
1021         { KRB5_ET_KRB5KRB_AP_ERR_BADSEQ, "KRB5KRB_AP_ERR_BADSEQ" },
1022         { KRB5_ET_KRB5KRB_AP_ERR_INAPP_CKSUM, "KRB5KRB_AP_ERR_INAPP_CKSUM" },
1023         { KRB5_ET_KRB5KDC_AP_PATH_NOT_ACCEPTED, "KRB5KDC_AP_PATH_NOT_ACCEPTED" },
1024         { KRB5_ET_KRB5KRB_ERR_RESPONSE_TOO_BIG, "KRB5KRB_ERR_RESPONSE_TOO_BIG"},
1025         { KRB5_ET_KRB5KRB_ERR_GENERIC, "KRB5KRB_ERR_GENERIC" },
1026         { KRB5_ET_KRB5KRB_ERR_FIELD_TOOLONG, "KRB5KRB_ERR_FIELD_TOOLONG" },
1027         { KRB5_ET_KDC_ERROR_CLIENT_NOT_TRUSTED, "KDC_ERROR_CLIENT_NOT_TRUSTED" },
1028         { KRB5_ET_KDC_ERROR_KDC_NOT_TRUSTED, "KDC_ERROR_KDC_NOT_TRUSTED" },
1029         { KRB5_ET_KDC_ERROR_INVALID_SIG, "KDC_ERROR_INVALID_SIG" },
1030         { KRB5_ET_KDC_ERR_KEY_TOO_WEAK, "KDC_ERR_KEY_TOO_WEAK" },
1031         { KRB5_ET_KDC_ERR_CERTIFICATE_MISMATCH, "KDC_ERR_CERTIFICATE_MISMATCH" },
1032         { KRB5_ET_KRB_AP_ERR_NO_TGT, "KRB_AP_ERR_NO_TGT" },
1033         { KRB5_ET_KDC_ERR_WRONG_REALM, "KDC_ERR_WRONG_REALM" },
1034         { KRB5_ET_KRB_AP_ERR_USER_TO_USER_REQUIRED, "KRB_AP_ERR_USER_TO_USER_REQUIRED" },
1035         { KRB5_ET_KDC_ERR_CANT_VERIFY_CERTIFICATE, "KDC_ERR_CANT_VERIFY_CERTIFICATE" },
1036         { KRB5_ET_KDC_ERR_INVALID_CERTIFICATE, "KDC_ERR_INVALID_CERTIFICATE" },
1037         { KRB5_ET_KDC_ERR_REVOKED_CERTIFICATE, "KDC_ERR_REVOKED_CERTIFICATE" },
1038         { KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNKNOWN, "KDC_ERR_REVOCATION_STATUS_UNKNOWN" },
1039         { KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNAVAILABLE, "KDC_ERR_REVOCATION_STATUS_UNAVAILABLE" },
1040         { KRB5_ET_KDC_ERR_CLIENT_NAME_MISMATCH, "KDC_ERR_CLIENT_NAME_MISMATCH" },
1041         { KRB5_ET_KDC_ERR_KDC_NAME_MISMATCH, "KDC_ERR_KDC_NAME_MISMATCH" },
1042         { 0, NULL }
1043 };
1044
1045
1046 #define PAC_LOGON_INFO          1
1047 #define PAC_CREDENTIAL_TYPE     2
1048 #define PAC_SERVER_CHECKSUM     6
1049 #define PAC_PRIVSVR_CHECKSUM    7
1050 #define PAC_CLIENT_INFO_TYPE    10
1051 #define PAC_S4U_DELEGATION_INFO 11
1052 #define PAC_UPN_DNS_INFO                12
1053 static const value_string w2k_pac_types[] = {
1054         { PAC_LOGON_INFO                , "Logon Info" },
1055         { PAC_CREDENTIAL_TYPE   , "Credential Type" },
1056         { PAC_SERVER_CHECKSUM   , "Server Checksum" },
1057         { PAC_PRIVSVR_CHECKSUM  , "Privsvr Checksum" },
1058         { PAC_CLIENT_INFO_TYPE  , "Client Info Type" },
1059         { PAC_S4U_DELEGATION_INFO, "S4U Delegation Info" },
1060         { PAC_UPN_DNS_INFO              , "UPN DNS Info" },
1061         { 0, NULL },
1062 };
1063
1064 static const value_string krb5_msg_types[] = {
1065         { KRB5_MSG_TICKET,              "Ticket" },
1066         { KRB5_MSG_AUTHENTICATOR,       "Authenticator" },
1067         { KRB5_MSG_ENC_TICKET_PART,     "EncTicketPart" },
1068         { KRB5_MSG_TGS_REQ,             "TGS-REQ" },
1069         { KRB5_MSG_TGS_REP,             "TGS-REP" },
1070         { KRB5_MSG_AS_REQ,              "AS-REQ" },
1071         { KRB5_MSG_AS_REP,              "AS-REP" },
1072         { KRB5_MSG_AP_REQ,              "AP-REQ" },
1073         { KRB5_MSG_AP_REP,              "AP-REP" },
1074         { KRB5_MSG_SAFE,                "KRB-SAFE" },
1075         { KRB5_MSG_PRIV,                "KRB-PRIV" },
1076         { KRB5_MSG_CRED,                "KRB-CRED" },
1077         { KRB5_MSG_ENC_AS_REP_PART,     "EncASRepPart" },
1078         { KRB5_MSG_ENC_TGS_REP_PART,    "EncTGSRepPart" },
1079         { KRB5_MSG_ENC_AP_REP_PART,     "EncAPRepPart" },
1080         { KRB5_MSG_ENC_KRB_PRIV_PART,   "EncKrbPrivPart" },
1081         { KRB5_MSG_ENC_KRB_CRED_PART,   "EncKrbCredPart" },
1082         { KRB5_MSG_ERROR,               "KRB-ERROR" },
1083         { 0, NULL },
1084 };
1085
1086 #define KRB5_GSS_C_DELEG_FLAG             0x01
1087 #define KRB5_GSS_C_MUTUAL_FLAG            0x02
1088 #define KRB5_GSS_C_REPLAY_FLAG            0x04
1089 #define KRB5_GSS_C_SEQUENCE_FLAG          0x08
1090 #define KRB5_GSS_C_CONF_FLAG              0x10
1091 #define KRB5_GSS_C_INTEG_FLAG             0x20
1092 #define KRB5_GSS_C_DCE_STYLE            0x1000
1093
1094 static const true_false_string tfs_gss_flags_deleg = {
1095         "Delegate credentials to remote peer",
1096         "Do NOT delegate"
1097 };
1098 static const true_false_string tfs_gss_flags_mutual = {
1099         "Request that remote peer authenticates itself",
1100         "Mutual authentication NOT required"
1101 };
1102 static const true_false_string tfs_gss_flags_replay = {
1103         "Enable replay protection for signed or sealed messages",
1104         "Do NOT enable replay protection"
1105 };
1106 static const true_false_string tfs_gss_flags_sequence = {
1107         "Enable Out-of-sequence detection for sign or sealed messages",
1108         "Do NOT enable out-of-sequence detection"
1109 };
1110 static const true_false_string tfs_gss_flags_conf = {
1111         "Confidentiality (sealing) may be invoked",
1112         "Do NOT use Confidentiality (sealing)"
1113 };
1114 static const true_false_string tfs_gss_flags_integ = {
1115         "Integrity protection (signing) may be invoked",
1116         "Do NOT use integrity protection"
1117 };
1118
1119 static const true_false_string tfs_gss_flags_dce_style = {
1120         "DCE-STYLE",
1121         "Not using DCE-STYLE"
1122 };
1123
1124 #ifdef HAVE_KERBEROS
1125 static int
1126 dissect_krb5_decrypt_ticket_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1127                                                                         proto_tree *tree, int hf_index _U_)
1128 {
1129         guint8 *plaintext;
1130         int length;
1131         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1132         tvbuff_t *next_tvb;
1133
1134         next_tvb=tvb_new_subset_remaining(tvb, offset);
1135         length=tvb_captured_length_remaining(tvb, offset);
1136
1137         /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
1138          * 7.5.1
1139          * All Ticket encrypted parts use usage == 2
1140          */
1141         plaintext=decrypt_krb5_data(tree, actx->pinfo, 2, next_tvb, private_data->etype, NULL);
1142
1143         if(plaintext){
1144                 tvbuff_t *child_tvb;
1145                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1146
1147                 /* Add the decrypted data to the data source list. */
1148                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1149
1150                 offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1151         }
1152         return offset;
1153 }
1154
1155 static int
1156 dissect_krb5_decrypt_authenticator_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1157                                                                                         proto_tree *tree, int hf_index _U_)
1158 {
1159         guint8 *plaintext;
1160         int length;
1161         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1162         tvbuff_t *next_tvb;
1163
1164         next_tvb=tvb_new_subset_remaining(tvb, offset);
1165         length=tvb_captured_length_remaining(tvb, offset);
1166
1167         /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
1168          * 7.5.1
1169          * Authenticators are encrypted with usage
1170          * == 7 or
1171          * == 11
1172          */
1173         plaintext=decrypt_krb5_data(tree, actx->pinfo, 7, next_tvb, private_data->etype, NULL);
1174
1175         if(!plaintext){
1176                 plaintext=decrypt_krb5_data(tree, actx->pinfo, 11, next_tvb, private_data->etype, NULL);
1177         }
1178
1179         if(plaintext){
1180                 tvbuff_t *child_tvb;
1181                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1182
1183                 /* Add the decrypted data to the data source list. */
1184                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1185
1186                 offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1187         }
1188         return offset;
1189 }
1190
1191 static int
1192 dissect_krb5_decrypt_KDC_REP_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1193                                                                         proto_tree *tree, int hf_index _U_)
1194 {
1195         guint8 *plaintext;
1196         int length;
1197         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1198         tvbuff_t *next_tvb;
1199
1200         next_tvb=tvb_new_subset_remaining(tvb, offset);
1201         length=tvb_captured_length_remaining(tvb, offset);
1202
1203         /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
1204          * 7.5.1
1205          * ASREP/TGSREP encryptedparts are encrypted with usage
1206          * == 3 or
1207          * == 8 or
1208          * == 9
1209          */
1210         plaintext=decrypt_krb5_data(tree, actx->pinfo, 3, next_tvb, private_data->etype, NULL);
1211
1212         if(!plaintext){
1213                 plaintext=decrypt_krb5_data(tree, actx->pinfo, 8, next_tvb, private_data->etype, NULL);
1214         }
1215
1216         if(!plaintext){
1217                 plaintext=decrypt_krb5_data(tree, actx->pinfo, 9, next_tvb, private_data->etype, NULL);
1218         }
1219
1220         if(plaintext){
1221                 tvbuff_t *child_tvb;
1222                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1223
1224                 /* Add the decrypted data to the data source list. */
1225                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1226
1227                 offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1228         }
1229         return offset;
1230 }
1231
1232 static int
1233 dissect_krb5_decrypt_PA_ENC_TIMESTAMP (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1234                                                                                 proto_tree *tree, int hf_index _U_)
1235 {
1236         guint8 *plaintext;
1237         int length;
1238         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1239         tvbuff_t *next_tvb;
1240
1241         next_tvb=tvb_new_subset_remaining(tvb, offset);
1242         length=tvb_captured_length_remaining(tvb, offset);
1243
1244         /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
1245          * 7.5.1
1246          * AS-REQ PA_ENC_TIMESTAMP are encrypted with usage
1247          * == 1
1248          */
1249         plaintext=decrypt_krb5_data(tree, actx->pinfo, 1, next_tvb, private_data->etype, NULL);
1250
1251         if(plaintext){
1252                 tvbuff_t *child_tvb;
1253                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1254
1255                 /* Add the decrypted data to the data source list. */
1256                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1257
1258                 offset=dissect_kerberos_PA_ENC_TS_ENC(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1259         }
1260         return offset;
1261 }
1262
1263 static int
1264 dissect_krb5_decrypt_AP_REP_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1265                                                                         proto_tree *tree, int hf_index _U_)
1266 {
1267         guint8 *plaintext;
1268         int length;
1269         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1270         tvbuff_t *next_tvb;
1271
1272         next_tvb=tvb_new_subset_remaining(tvb, offset);
1273         length=tvb_captured_length_remaining(tvb, offset);
1274
1275         /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
1276          * 7.5.1
1277          * AP-REP are encrypted with usage == 12
1278          */
1279         plaintext=decrypt_krb5_data(tree, actx->pinfo, 12, next_tvb, private_data->etype, NULL);
1280
1281         if(plaintext){
1282                 tvbuff_t *child_tvb;
1283                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1284
1285                 /* Add the decrypted data to the data source list. */
1286                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1287
1288                 offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1289         }
1290         return offset;
1291 }
1292
1293 static int
1294 dissect_krb5_decrypt_PRIV_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1295                                                                         proto_tree *tree, int hf_index _U_)
1296 {
1297         guint8 *plaintext;
1298         int length;
1299         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1300         tvbuff_t *next_tvb;
1301
1302         next_tvb=tvb_new_subset_remaining(tvb, offset);
1303         length=tvb_captured_length_remaining(tvb, offset);
1304
1305         /* RFC4120 :
1306          * EncKrbPrivPart encrypted with usage
1307          * == 13
1308          */
1309         plaintext=decrypt_krb5_data(tree, actx->pinfo, 13, next_tvb, private_data->etype, NULL);
1310
1311         if(plaintext){
1312                 tvbuff_t *child_tvb;
1313                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1314
1315                 /* Add the decrypted data to the data source list. */
1316                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1317
1318                 offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1319         }
1320         return offset;
1321 }
1322
1323 static int
1324 dissect_krb5_decrypt_CRED_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1325                                                                         proto_tree *tree, int hf_index _U_)
1326 {
1327         guint8 *plaintext;
1328         int length;
1329         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1330         tvbuff_t *next_tvb;
1331
1332         next_tvb=tvb_new_subset_remaining(tvb, offset);
1333         length=tvb_captured_length_remaining(tvb, offset);
1334
1335         /* RFC4120 :
1336          * EncKrbCredPart encrypted with usage
1337          * == 14
1338          */
1339         plaintext=decrypt_krb5_data(tree, actx->pinfo, 14, next_tvb, private_data->etype, NULL);
1340
1341         if(plaintext){
1342                 tvbuff_t *child_tvb;
1343                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1344
1345                 /* Add the decrypted data to the data source list. */
1346                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1347
1348                 offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1349         }
1350         return offset;
1351 }
1352
1353 static int
1354 dissect_krb5_decrypt_KrbFastReq(gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1355                                 proto_tree *tree, int hf_index _U_)
1356 {
1357         guint8 *plaintext;
1358         int length;
1359         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1360         tvbuff_t *next_tvb;
1361
1362         next_tvb=tvb_new_subset_remaining(tvb, offset);
1363         length=tvb_captured_length_remaining(tvb, offset);
1364
1365         /* RFC6113 :
1366          * KrbFastResponse encrypted with usage
1367          * KEY_USAGE_FAST_ENC 51
1368          */
1369         plaintext=decrypt_krb5_data(tree, actx->pinfo, KEY_USAGE_FAST_ENC,
1370                                     next_tvb, private_data->etype, NULL);
1371
1372         if(plaintext){
1373                 tvbuff_t *child_tvb;
1374                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1375                 tvb_set_free_cb(child_tvb, g_free);
1376
1377                 /* Add the decrypted data to the data source list. */
1378                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1379
1380                 offset=dissect_kerberos_KrbFastReq(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1381         }
1382         return offset;
1383 }
1384
1385 static int
1386 dissect_krb5_decrypt_KrbFastResponse(gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1387                                      proto_tree *tree, int hf_index _U_)
1388 {
1389         guint8 *plaintext;
1390         int length;
1391         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1392         tvbuff_t *next_tvb;
1393
1394         next_tvb=tvb_new_subset_remaining(tvb, offset);
1395         length=tvb_captured_length_remaining(tvb, offset);
1396
1397         /*
1398          * RFC6113 :
1399          * KrbFastResponse encrypted with usage
1400          * KEY_USAGE_FAST_REP 52
1401          */
1402         plaintext=decrypt_krb5_data(tree, actx->pinfo, KEY_USAGE_FAST_REP,
1403                                     next_tvb, private_data->etype, NULL);
1404
1405         if(plaintext){
1406                 tvbuff_t *child_tvb;
1407                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1408                 tvb_set_free_cb(child_tvb, g_free);
1409
1410                 /* Add the decrypted data to the data source list. */
1411                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1412
1413                 offset=dissect_kerberos_KrbFastResponse(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1414         }
1415         return offset;
1416 }
1417
1418 static int
1419 dissect_krb5_decrypt_EncryptedChallenge(gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1420                                         proto_tree *tree, int hf_index _U_)
1421 {
1422         guint8 *plaintext;
1423         int length;
1424         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1425         tvbuff_t *next_tvb;
1426         int usage = 0;
1427
1428         next_tvb=tvb_new_subset_remaining(tvb, offset);
1429         length=tvb_captured_length_remaining(tvb, offset);
1430
1431         /* RFC6113 :
1432          * KEY_USAGE_ENC_CHALLENGE_CLIENT  54
1433          * KEY_USAGE_ENC_CHALLENGE_KDC     55
1434          */
1435         if (private_data->kdc_response) {
1436                 usage = KEY_USAGE_ENC_CHALLENGE_KDC;
1437         } else {
1438                 usage = KEY_USAGE_ENC_CHALLENGE_CLIENT;
1439         }
1440         plaintext=decrypt_krb5_data(tree, actx->pinfo, usage, next_tvb, private_data->etype, NULL);
1441
1442         if(plaintext){
1443                 tvbuff_t *child_tvb;
1444                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1445                 tvb_set_free_cb(child_tvb, g_free);
1446
1447                 /* Add the decrypted data to the data source list. */
1448                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1449
1450                 offset=dissect_kerberos_PA_ENC_TS_ENC(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1451         }
1452         return offset;
1453 }
1454 #endif
1455
1456 static const int *hf_krb_pa_supported_enctypes_fields[] = {
1457         &hf_krb_pa_supported_enctypes_des_cbc_crc,
1458         &hf_krb_pa_supported_enctypes_des_cbc_md5,
1459         &hf_krb_pa_supported_enctypes_rc4_hmac,
1460         &hf_krb_pa_supported_enctypes_aes128_cts_hmac_sha1_96,
1461         &hf_krb_pa_supported_enctypes_aes256_cts_hmac_sha1_96,
1462         &hf_krb_pa_supported_enctypes_fast_supported,
1463         &hf_krb_pa_supported_enctypes_compound_identity_supported,
1464         &hf_krb_pa_supported_enctypes_claims_supported,
1465         &hf_krb_pa_supported_enctypes_resource_sid_compression_disabled,
1466         NULL,
1467 };
1468
1469 static const true_false_string supported_tfs = {
1470         "Supported", "Not supported"
1471 };
1472
1473 static int
1474 dissect_kerberos_PA_SUPPORTED_ENCTYPES(gboolean implicit_tag _U_, tvbuff_t *tvb _U_,
1475                                        int offset _U_, asn1_ctx_t *actx _U_,
1476                                        proto_tree *tree _U_, int hf_index _U_)
1477 {
1478         actx->created_item = proto_tree_add_bitmask(tree, tvb, offset,
1479                                                     hf_krb_pa_supported_enctypes,
1480                                                     ett_krb_pa_supported_enctypes,
1481                                                     hf_krb_pa_supported_enctypes_fields,
1482                                                     ENC_LITTLE_ENDIAN);
1483         offset += 4;
1484
1485         return offset;
1486 }
1487
1488 static const int *hf_krb_ad_ap_options_fields[] = {
1489         &hf_krb_ad_ap_options_cbt,
1490         NULL,
1491 };
1492
1493 static const true_false_string set_tfs = {
1494         "Set", "Not set"
1495 };
1496
1497 static int
1498 dissect_kerberos_AD_AP_OPTIONS(gboolean implicit_tag _U_, tvbuff_t *tvb _U_,
1499                                int offset _U_, asn1_ctx_t *actx _U_,
1500                                proto_tree *tree _U_, int hf_index _U_)
1501 {
1502         actx->created_item = proto_tree_add_bitmask(tree, tvb, offset,
1503                                                     hf_krb_ad_ap_options,
1504                                                     ett_krb_ad_ap_options,
1505                                                     hf_krb_ad_ap_options_fields,
1506                                                     ENC_LITTLE_ENDIAN);
1507         offset += 4;
1508
1509         return offset;
1510 }
1511 /* Dissect a GSSAPI checksum as per RFC1964. This is NOT ASN.1 encoded.
1512  */
1513 static int
1514 dissect_krb5_rfc1964_checksum(asn1_ctx_t *actx _U_, proto_tree *tree, tvbuff_t *tvb)
1515 {
1516         int offset=0;
1517         guint32 len;
1518         guint16 dlglen;
1519
1520         /* Length of Bnd field */
1521         len=tvb_get_letohl(tvb, offset);
1522         proto_tree_add_item(tree, hf_krb_gssapi_len, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1523         offset += 4;
1524
1525         /* Bnd field */
1526         proto_tree_add_item(tree, hf_krb_gssapi_bnd, tvb, offset, len, ENC_NA);
1527         offset += len;
1528
1529
1530         /* flags */
1531         proto_tree_add_item(tree, hf_krb_gssapi_c_flag_dce_style, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1532         proto_tree_add_item(tree, hf_krb_gssapi_c_flag_integ, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1533         proto_tree_add_item(tree, hf_krb_gssapi_c_flag_conf, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1534         proto_tree_add_item(tree, hf_krb_gssapi_c_flag_sequence, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1535         proto_tree_add_item(tree, hf_krb_gssapi_c_flag_replay, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1536         proto_tree_add_item(tree, hf_krb_gssapi_c_flag_mutual, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1537         proto_tree_add_item(tree, hf_krb_gssapi_c_flag_deleg, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1538         offset += 4;
1539
1540         /* the next fields are optional so we have to check that we have
1541          * more data in our buffers */
1542         if(tvb_reported_length_remaining(tvb, offset)<2){
1543                 return offset;
1544         }
1545         /* dlgopt identifier */
1546         proto_tree_add_item(tree, hf_krb_gssapi_dlgopt, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1547         offset += 2;
1548
1549         if(tvb_reported_length_remaining(tvb, offset)<2){
1550                 return offset;
1551         }
1552         /* dlglen identifier */
1553         dlglen=tvb_get_letohs(tvb, offset);
1554         proto_tree_add_item(tree, hf_krb_gssapi_dlglen, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1555         offset += 2;
1556
1557         if(dlglen!=tvb_reported_length_remaining(tvb, offset)){
1558                 proto_tree_add_expert_format(tree, actx->pinfo, &ei_krb_gssapi_dlglen, tvb, 0, 0,
1559                                 "Error: DlgLen:%d is not the same as number of bytes remaining:%d", dlglen, tvb_captured_length_remaining(tvb, offset));
1560                 return offset;
1561         }
1562
1563         /* this should now be a KRB_CRED message */
1564         offset=dissect_kerberos_Applications(FALSE, tvb, offset, actx, tree, /* hf_index */ -1);
1565
1566         return offset;
1567 }
1568
1569 static int
1570 dissect_krb5_PA_PROV_SRV_LOCATION(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)
1571 {
1572         offset=dissect_ber_GeneralString(actx, tree, tvb, offset, hf_krb_provsrv_location, NULL, 0);
1573
1574         return offset;
1575 }
1576
1577 static int
1578 dissect_krb5_PW_SALT(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)
1579 {
1580         guint32 nt_status;
1581
1582         /* Microsoft stores a special 12 byte blob here
1583          * guint32 NT_status
1584          * guint32 unknown
1585          * guint32 unknown
1586          * decode everything as this blob for now until we see if anyone
1587          * else ever uses it   or we learn how to tell whether this
1588          * is such an MS blob or not.
1589          */
1590         proto_tree_add_item(tree, hf_krb_smb_nt_status, tvb, offset, 4,
1591                         ENC_LITTLE_ENDIAN);
1592         nt_status=tvb_get_letohl(tvb, offset);
1593         if(nt_status) {
1594                 col_append_fstr(actx->pinfo->cinfo, COL_INFO,
1595                         " NT Status: %s",
1596                         val_to_str(nt_status, NT_errors,
1597                         "Unknown error code %#x"));
1598         }
1599         offset += 4;
1600
1601         proto_tree_add_item(tree, hf_krb_smb_unknown, tvb, offset, 4,
1602                         ENC_LITTLE_ENDIAN);
1603         offset += 4;
1604
1605         proto_tree_add_item(tree, hf_krb_smb_unknown, tvb, offset, 4,
1606                         ENC_LITTLE_ENDIAN);
1607         offset += 4;
1608
1609         return offset;
1610 }
1611
1612 static int
1613 dissect_krb5_PAC_DREP(proto_tree *parent_tree, tvbuff_t *tvb, int offset, guint8 *drep)
1614 {
1615         proto_tree *tree;
1616         guint8 val;
1617
1618         tree = proto_tree_add_subtree(parent_tree, tvb, offset, 16, ett_krb_pac_drep, NULL, "DREP");
1619
1620         val = tvb_get_guint8(tvb, offset);
1621         proto_tree_add_uint(tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, val>>4);
1622
1623         offset++;
1624
1625         if (drep) {
1626                 *drep = val;
1627         }
1628
1629         return offset;
1630 }
1631
1632 /* This might be some sort of header that MIDL generates when creating
1633  * marshalling/unmarshalling code for blobs that are not to be transported
1634  * ontop of DCERPC and where the DREP fields specifying things such as
1635  * endianess and similar are not available.
1636  */
1637 static int
1638 dissect_krb5_PAC_NDRHEADERBLOB(proto_tree *parent_tree, tvbuff_t *tvb, int offset, guint8 *drep, asn1_ctx_t *actx _U_)
1639 {
1640         proto_tree *tree;
1641
1642         tree = proto_tree_add_subtree(parent_tree, tvb, offset, 16, ett_krb_pac_midl_blob, NULL, "MES header");
1643
1644         /* modified DREP field that is used for stuff that is transporetd ontop
1645            of non dcerpc
1646         */
1647         proto_tree_add_item(tree, hf_krb_midl_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1648         offset++;
1649
1650         offset = dissect_krb5_PAC_DREP(tree, tvb, offset, drep);
1651
1652
1653         proto_tree_add_item(tree, hf_krb_midl_hdr_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1654         offset+=2;
1655
1656         proto_tree_add_item(tree, hf_krb_midl_fill_bytes, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1657         offset += 4;
1658
1659         /* length of blob that follows */
1660         proto_tree_add_item(tree, hf_krb_midl_blob_len, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1661         offset += 8;
1662
1663         return offset;
1664 }
1665
1666 static int
1667 dissect_krb5_PAC_LOGON_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1668 {
1669         proto_item *item;
1670         proto_tree *tree;
1671         guint8 drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
1672         static dcerpc_info di;      /* fake dcerpc_info struct */
1673         static dcerpc_call_value call_data;
1674
1675         item = proto_tree_add_item(parent_tree, hf_krb_pac_logon_info, tvb, offset, -1, ENC_NA);
1676         tree = proto_item_add_subtree(item, ett_krb_pac_logon_info);
1677
1678         /* skip the first 16 bytes, they are some magic created by the idl
1679          * compiler   the first 4 bytes might be flags?
1680          */
1681         offset = dissect_krb5_PAC_NDRHEADERBLOB(tree, tvb, offset, &drep[0], actx);
1682
1683         /* the PAC_LOGON_INFO blob */
1684         /* fake whatever state the dcerpc runtime support needs */
1685         di.conformant_run=0;
1686         /* we need di->call_data->flags.NDR64 == 0 */
1687         di.call_data=&call_data;
1688         init_ndr_pointer_list(&di);
1689         offset = dissect_ndr_pointer(tvb, offset, actx->pinfo, tree, &di, drep,
1690                                                                         netlogon_dissect_PAC_LOGON_INFO, NDR_POINTER_UNIQUE,
1691                                                                         "PAC_LOGON_INFO:", -1);
1692
1693         return offset;
1694 }
1695
1696 static int
1697 dissect_krb5_PAC_S4U_DELEGATION_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx)
1698 {
1699         proto_item *item;
1700         proto_tree *tree;
1701         guint8 drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
1702         static dcerpc_info di;      /* fake dcerpc_info struct */
1703         static dcerpc_call_value call_data;
1704
1705         item = proto_tree_add_item(parent_tree, hf_krb_pac_s4u_delegation_info, tvb, offset, -1, ENC_NA);
1706         tree = proto_item_add_subtree(item, ett_krb_pac_s4u_delegation_info);
1707
1708         /* skip the first 16 bytes, they are some magic created by the idl
1709          * compiler   the first 4 bytes might be flags?
1710          */
1711         offset = dissect_krb5_PAC_NDRHEADERBLOB(tree, tvb, offset, &drep[0], actx);
1712
1713
1714         /* the S4U_DELEGATION_INFO blob. See [MS-PAC] */
1715         /* fake whatever state the dcerpc runtime support needs */
1716         di.conformant_run=0;
1717         /* we need di->call_data->flags.NDR64 == 0 */
1718         di.call_data=&call_data;
1719         init_ndr_pointer_list(&di);
1720         offset = dissect_ndr_pointer(tvb, offset, actx->pinfo, tree, &di, drep,
1721                                                                         netlogon_dissect_PAC_S4U_DELEGATION_INFO, NDR_POINTER_UNIQUE,
1722                                                                         "PAC_S4U_DELEGATION_INFO:", -1);
1723
1724         return offset;
1725 }
1726
1727 static int
1728 dissect_krb5_PAC_UPN_DNS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1729 {
1730         proto_item *item;
1731         proto_tree *tree;
1732         guint16 dns_offset, dns_len;
1733         guint16 upn_offset, upn_len;
1734         const char *dn;
1735         int dn_len;
1736         guint16 bc;
1737
1738         item = proto_tree_add_item(parent_tree, hf_krb_pac_upn_dns_info, tvb, offset, -1, ENC_NA);
1739         tree = proto_item_add_subtree(item, ett_krb_pac_upn_dns_info);
1740
1741         /* upn */
1742         upn_len = tvb_get_letohs(tvb, offset);
1743         proto_tree_add_item(tree, hf_krb_pac_upn_upn_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1744         offset+=2;
1745         upn_offset = tvb_get_letohs(tvb, offset);
1746         proto_tree_add_item(tree, hf_krb_pac_upn_upn_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1747         offset+=2;
1748
1749         /* dns */
1750         dns_len = tvb_get_letohs(tvb, offset);
1751         proto_tree_add_item(tree, hf_krb_pac_upn_dns_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1752         offset+=2;
1753         dns_offset = tvb_get_letohs(tvb, offset);
1754         proto_tree_add_item(tree, hf_krb_pac_upn_dns_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1755         offset+=2;
1756
1757         /* flags */
1758         proto_tree_add_item(tree, hf_krb_pac_upn_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1759
1760         /* upn */
1761         offset = upn_offset;
1762         dn_len = upn_len;
1763         bc = tvb_reported_length_remaining(tvb, offset);
1764         dn = get_unicode_or_ascii_string(tvb, &offset, TRUE, &dn_len, TRUE, TRUE, &bc);
1765         proto_tree_add_string(tree, hf_krb_pac_upn_upn_name, tvb, upn_offset, upn_len, dn);
1766
1767         /* dns */
1768         offset = dns_offset;
1769         dn_len = dns_len;
1770         bc = tvb_reported_length_remaining(tvb, offset);
1771         dn = get_unicode_or_ascii_string(tvb, &offset, TRUE, &dn_len, TRUE, TRUE, &bc);
1772         proto_tree_add_string(tree, hf_krb_pac_upn_dns_name, tvb, dns_offset, dns_len, dn);
1773
1774         return offset;
1775 }
1776
1777 static int
1778 dissect_krb5_PAC_CREDENTIAL_TYPE(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1779 {
1780         proto_tree_add_item(parent_tree, hf_krb_pac_credential_type, tvb, offset, -1, ENC_NA);
1781
1782         return offset;
1783 }
1784
1785 static int
1786 dissect_krb5_PAC_SERVER_CHECKSUM(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1787 {
1788         proto_item *item;
1789         proto_tree *tree;
1790
1791         item = proto_tree_add_item(parent_tree, hf_krb_pac_server_checksum, tvb, offset, -1, ENC_NA);
1792         tree = proto_item_add_subtree(item, ett_krb_pac_server_checksum);
1793
1794         /* signature type */
1795         proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1796         offset+=4;
1797
1798         /* signature data */
1799         proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, -1, ENC_NA);
1800
1801         return offset;
1802 }
1803
1804 static int
1805 dissect_krb5_PAC_PRIVSVR_CHECKSUM(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1806 {
1807         proto_item *item;
1808         proto_tree *tree;
1809
1810         item = proto_tree_add_item(parent_tree, hf_krb_pac_privsvr_checksum, tvb, offset, -1, ENC_NA);
1811         tree = proto_item_add_subtree(item, ett_krb_pac_privsvr_checksum);
1812
1813         /* signature type */
1814         proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1815         offset+=4;
1816
1817         /* signature data */
1818         proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, -1, ENC_NA);
1819
1820         return offset;
1821 }
1822
1823 static int
1824 dissect_krb5_PAC_CLIENT_INFO_TYPE(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1825 {
1826         proto_item *item;
1827         proto_tree *tree;
1828         guint16 namelen;
1829
1830         item = proto_tree_add_item(parent_tree, hf_krb_pac_client_info_type, tvb, offset, -1, ENC_NA);
1831         tree = proto_item_add_subtree(item, ett_krb_pac_client_info_type);
1832
1833         /* clientid */
1834         offset = dissect_nt_64bit_time(tvb, tree, offset, hf_krb_pac_clientid);
1835
1836         /* name length */
1837         namelen=tvb_get_letohs(tvb, offset);
1838         proto_tree_add_uint(tree, hf_krb_pac_namelen, tvb, offset, 2, namelen);
1839         offset+=2;
1840
1841         /* client name */
1842         proto_tree_add_item(tree, hf_krb_pac_clientname, tvb, offset, namelen, ENC_UTF_16|ENC_LITTLE_ENDIAN);
1843         offset+=namelen;
1844
1845         return offset;
1846 }
1847
1848 static int
1849 dissect_krb5_AD_WIN2K_PAC_struct(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx)
1850 {
1851         guint32 pac_type;
1852         guint32 pac_size;
1853         guint32 pac_offset;
1854         proto_item *it=NULL;
1855         proto_tree *tr=NULL;
1856         tvbuff_t *next_tvb;
1857
1858         /* type of pac data */
1859         pac_type=tvb_get_letohl(tvb, offset);
1860         it=proto_tree_add_uint(tree, hf_krb_w2k_pac_type, tvb, offset, 4, pac_type);
1861         tr=proto_item_add_subtree(it, ett_krb_pac);
1862
1863         offset += 4;
1864
1865         /* size of pac data */
1866         pac_size=tvb_get_letohl(tvb, offset);
1867         proto_tree_add_uint(tr, hf_krb_w2k_pac_size, tvb, offset, 4, pac_size);
1868         offset += 4;
1869
1870         /* offset to pac data */
1871         pac_offset=tvb_get_letohl(tvb, offset);
1872         proto_tree_add_uint(tr, hf_krb_w2k_pac_offset, tvb, offset, 4, pac_offset);
1873         offset += 8;
1874
1875         next_tvb=tvb_new_subset_length_caplen(tvb, pac_offset, pac_size, pac_size);
1876         switch(pac_type){
1877         case PAC_LOGON_INFO:
1878                 dissect_krb5_PAC_LOGON_INFO(tr, next_tvb, 0, actx);
1879                 break;
1880         case PAC_CREDENTIAL_TYPE:
1881                 dissect_krb5_PAC_CREDENTIAL_TYPE(tr, next_tvb, 0, actx);
1882                 break;
1883         case PAC_SERVER_CHECKSUM:
1884                 dissect_krb5_PAC_SERVER_CHECKSUM(tr, next_tvb, 0, actx);
1885                 break;
1886         case PAC_PRIVSVR_CHECKSUM:
1887                 dissect_krb5_PAC_PRIVSVR_CHECKSUM(tr, next_tvb, 0, actx);
1888                 break;
1889         case PAC_CLIENT_INFO_TYPE:
1890                 dissect_krb5_PAC_CLIENT_INFO_TYPE(tr, next_tvb, 0, actx);
1891                 break;
1892         case PAC_S4U_DELEGATION_INFO:
1893                 dissect_krb5_PAC_S4U_DELEGATION_INFO(tr, next_tvb, 0, actx);
1894                 break;
1895         case PAC_UPN_DNS_INFO:
1896                 dissect_krb5_PAC_UPN_DNS_INFO(tr, next_tvb, 0, actx);
1897                 break;
1898
1899         default:
1900                 break;
1901         }
1902         return offset;
1903 }
1904
1905 static int
1906 dissect_krb5_AD_WIN2K_PAC(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index _U_)
1907 {
1908         guint32 entries;
1909         guint32 version;
1910         guint32 i;
1911
1912         /* first in the PAC structure comes the number of entries */
1913         entries=tvb_get_letohl(tvb, offset);
1914         proto_tree_add_uint(tree, hf_krb_w2k_pac_entries, tvb, offset, 4, entries);
1915         offset += 4;
1916
1917         /* second comes the version */
1918         version=tvb_get_letohl(tvb, offset);
1919         proto_tree_add_uint(tree, hf_krb_w2k_pac_version, tvb, offset, 4, version);
1920         offset += 4;
1921
1922         for(i=0;i<entries;i++){
1923                 offset=dissect_krb5_AD_WIN2K_PAC_struct(tree, tvb, offset, actx);
1924         }
1925
1926         return offset;
1927 }
1928
1929 #include "packet-kerberos-fn.c"
1930
1931 /* Make wrappers around exported functions for now */
1932 int
1933 dissect_krb5_Checksum(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1934 {
1935         return dissect_kerberos_Checksum(FALSE, tvb, offset, actx, tree, hf_kerberos_cksum);
1936
1937 }
1938
1939 int
1940 dissect_krb5_ctime(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1941 {
1942         return dissect_kerberos_KerberosTime(FALSE, tvb, offset, actx, tree, hf_kerberos_ctime);
1943 }
1944
1945
1946 int
1947 dissect_krb5_cname(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1948 {
1949         return dissect_kerberos_PrincipalName(FALSE, tvb, offset, actx, tree, hf_kerberos_cname);
1950 }
1951 int
1952 dissect_krb5_realm(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1953 {
1954         return dissect_kerberos_Realm(FALSE, tvb, offset, actx, tree, hf_kerberos_realm);
1955 }
1956
1957
1958 static gint
1959 dissect_kerberos_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1960     gboolean dci, gboolean do_col_protocol, gboolean have_rm,
1961     kerberos_callbacks *cb)
1962 {
1963         volatile int offset = 0;
1964         proto_tree *volatile kerberos_tree = NULL;
1965         proto_item *volatile item = NULL;
1966         asn1_ctx_t asn1_ctx;
1967
1968         /* TCP record mark and length */
1969         guint32 krb_rm = 0;
1970         gint krb_reclen = 0;
1971
1972         gbl_do_col_info=dci;
1973
1974         if (have_rm) {
1975                 krb_rm = tvb_get_ntohl(tvb, offset);
1976                 krb_reclen = kerberos_rm_to_reclen(krb_rm);
1977                 /*
1978                  * What is a reasonable size limit?
1979                  */
1980                 if (krb_reclen > 10 * 1024 * 1024) {
1981                         return (-1);
1982                 }
1983
1984                 if (do_col_protocol) {
1985                         col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
1986                 }
1987
1988                 if (tree) {
1989                         item = proto_tree_add_item(tree, proto_kerberos, tvb, 0, -1, ENC_NA);
1990                         kerberos_tree = proto_item_add_subtree(item, ett_kerberos);
1991                 }
1992
1993                 show_krb_recordmark(kerberos_tree, tvb, offset, krb_rm);
1994                 offset += 4;
1995         } else {
1996                 /* Do some sanity checking here,
1997                  * All krb5 packets start with a TAG class that is BER_CLASS_APP
1998                  * and a tag value that is either of the values below:
1999                  * If it doesn't look like kerberos, return 0 and let someone else have
2000                  * a go at it.
2001                  */
2002                 gint8 tmp_class;
2003                 gboolean tmp_pc;
2004                 gint32 tmp_tag;
2005
2006                 get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag);
2007                 if(tmp_class!=BER_CLASS_APP){
2008                         return 0;
2009                 }
2010                 switch(tmp_tag){
2011                         case KRB5_MSG_TICKET:
2012                         case KRB5_MSG_AUTHENTICATOR:
2013                         case KRB5_MSG_ENC_TICKET_PART:
2014                         case KRB5_MSG_AS_REQ:
2015                         case KRB5_MSG_AS_REP:
2016                         case KRB5_MSG_TGS_REQ:
2017                         case KRB5_MSG_TGS_REP:
2018                         case KRB5_MSG_AP_REQ:
2019                         case KRB5_MSG_AP_REP:
2020                         case KRB5_MSG_ENC_AS_REP_PART:
2021                         case KRB5_MSG_ENC_TGS_REP_PART:
2022                         case KRB5_MSG_ENC_AP_REP_PART:
2023                         case KRB5_MSG_ENC_KRB_PRIV_PART:
2024                         case KRB5_MSG_ENC_KRB_CRED_PART:
2025                         case KRB5_MSG_SAFE:
2026                         case KRB5_MSG_PRIV:
2027                         case KRB5_MSG_ERROR:
2028                                 break;
2029                         default:
2030                                 return 0;
2031                 }
2032         if (do_col_protocol) {
2033                         col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
2034         }
2035         if (gbl_do_col_info) {
2036                         col_clear(pinfo->cinfo, COL_INFO);
2037                 }
2038                 if (tree) {
2039                         item = proto_tree_add_item(tree, proto_kerberos, tvb, 0, -1, ENC_NA);
2040                         kerberos_tree = proto_item_add_subtree(item, ett_kerberos);
2041                 }
2042         }
2043         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
2044         asn1_ctx.private_data = cb;
2045
2046         TRY {
2047                 offset=dissect_kerberos_Applications(FALSE, tvb, offset, &asn1_ctx , kerberos_tree, /* hf_index */ -1);
2048         } CATCH_BOUNDS_ERRORS {
2049                 RETHROW;
2050         } ENDTRY;
2051
2052         proto_item_set_len(item, offset);
2053         return offset;
2054 }
2055
2056 /*
2057  * Display the TCP record mark.
2058  */
2059 void
2060 show_krb_recordmark(proto_tree *tree, tvbuff_t *tvb, gint start, guint32 krb_rm)
2061 {
2062         gint rec_len;
2063         proto_tree *rm_tree;
2064
2065         if (tree == NULL)
2066                 return;
2067
2068         rec_len = kerberos_rm_to_reclen(krb_rm);
2069         rm_tree = proto_tree_add_subtree_format(tree, tvb, start, 4, ett_krb_recordmark, NULL,
2070                 "Record Mark: %u %s", rec_len, plurality(rec_len, "byte", "bytes"));
2071         proto_tree_add_boolean(rm_tree, hf_krb_rm_reserved, tvb, start, 4, krb_rm);
2072         proto_tree_add_uint(rm_tree, hf_krb_rm_reclen, tvb, start, 4, krb_rm);
2073 }
2074
2075 gint
2076 dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int do_col_info, kerberos_callbacks *cb)
2077 {
2078         return (dissect_kerberos_common(tvb, pinfo, tree, do_col_info, FALSE, FALSE, cb));
2079 }
2080
2081 guint32
2082 kerberos_output_keytype(void)
2083 {
2084         return gbl_keytype;
2085 }
2086
2087 static gint
2088 dissect_kerberos_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2089 {
2090         /* Some weird kerberos implementation apparently do krb4 on the krb5 port.
2091            Since all (except weirdo transarc krb4 stuff) use
2092            an opcode <=16 in the first byte, use this to see if it might
2093            be krb4.
2094            All krb5 commands start with an APPL tag and thus is >=0x60
2095            so if first byte is <=16  just blindly assume it is krb4 then
2096         */
2097         if(tvb_captured_length(tvb) >= 1 && tvb_get_guint8(tvb, 0)<=0x10){
2098                 if(krb4_handle){
2099                         gboolean res;
2100
2101                         res=call_dissector_only(krb4_handle, tvb, pinfo, tree, NULL);
2102                         return res;
2103                 }else{
2104                         return 0;
2105                 }
2106         }
2107
2108
2109         return dissect_kerberos_common(tvb, pinfo, tree, TRUE, TRUE, FALSE, NULL);
2110 }
2111
2112 gint
2113 kerberos_rm_to_reclen(guint krb_rm)
2114 {
2115     return (krb_rm & KRB_RM_RECLEN);
2116 }
2117
2118 guint
2119 get_krb_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
2120 {
2121         guint krb_rm;
2122         gint pdulen;
2123
2124         krb_rm = tvb_get_ntohl(tvb, offset);
2125         pdulen = kerberos_rm_to_reclen(krb_rm);
2126         return (pdulen + 4);
2127 }
2128 static void
2129 kerberos_prefs_apply_cb(void) {
2130 #ifdef HAVE_LIBNETTLE
2131         clear_keytab();
2132         read_keytab_file(keytab_filename);
2133 #endif
2134 }
2135
2136 static int
2137 dissect_kerberos_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2138 {
2139         pinfo->fragmented = TRUE;
2140         if (dissect_kerberos_common(tvb, pinfo, tree, TRUE, TRUE, TRUE, NULL) < 0) {
2141                 /*
2142                  * The dissector failed to recognize this as a valid
2143                  * Kerberos message.  Mark it as a continuation packet.
2144                  */
2145                 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
2146         }
2147
2148         return tvb_captured_length(tvb);
2149 }
2150
2151 static int
2152 dissect_kerberos_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
2153 {
2154         col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
2155         col_clear(pinfo->cinfo, COL_INFO);
2156
2157         tcp_dissect_pdus(tvb, pinfo, tree, krb_desegment, 4, get_krb_pdu_len,
2158                                          dissect_kerberos_tcp_pdu, data);
2159         return tvb_captured_length(tvb);
2160 }
2161
2162 /*--- proto_register_kerberos -------------------------------------------*/
2163 void proto_register_kerberos(void) {
2164
2165         /* List of fields */
2166
2167         static hf_register_info hf[] = {
2168         { &hf_krb_rm_reserved, {
2169                 "Reserved", "kerberos.rm.reserved", FT_BOOLEAN, 32,
2170                 TFS(&tfs_set_notset), KRB_RM_RESERVED, "Record mark reserved bit", HFILL }},
2171         { &hf_krb_rm_reclen, {
2172                 "Record Length", "kerberos.rm.length", FT_UINT32, BASE_DEC,
2173                 NULL, KRB_RM_RECLEN, NULL, HFILL }},
2174         { &hf_krb_provsrv_location, {
2175                 "PROVSRV Location", "kerberos.provsrv_location", FT_STRING, BASE_NONE,
2176                 NULL, 0, "PacketCable PROV SRV Location", HFILL }},
2177         { &hf_krb_smb_nt_status,
2178                 { "NT Status", "kerberos.smb.nt_status", FT_UINT32, BASE_HEX,
2179                 VALS(NT_errors), 0, "NT Status code", HFILL }},
2180         { &hf_krb_smb_unknown,
2181                 { "Unknown", "kerberos.smb.unknown", FT_UINT32, BASE_HEX,
2182                 NULL, 0, NULL, HFILL }},
2183         { &hf_krb_address_ip, {
2184                 "IP Address", "kerberos.addr_ip", FT_IPv4, BASE_NONE,
2185                 NULL, 0, NULL, HFILL }},
2186         { &hf_krb_address_ipv6, {
2187                 "IPv6 Address", "kerberos.addr_ipv6", FT_IPv6, BASE_NONE,
2188                 NULL, 0, NULL, HFILL }},
2189         { &hf_krb_address_netbios, {
2190                 "NetBIOS Address", "kerberos.addr_nb", FT_STRING, BASE_NONE,
2191                 NULL, 0, "NetBIOS Address and type", HFILL }},
2192         { &hf_krb_gssapi_len, {
2193                 "Length", "kerberos.gssapi.len", FT_UINT32, BASE_DEC,
2194                 NULL, 0, "Length of GSSAPI Bnd field", HFILL }},
2195         { &hf_krb_gssapi_bnd, {
2196                 "Bnd", "kerberos.gssapi.bdn", FT_BYTES, BASE_NONE,
2197                 NULL, 0, "GSSAPI Bnd field", HFILL }},
2198         { &hf_krb_gssapi_c_flag_deleg, {
2199                 "Deleg", "kerberos.gssapi.checksum.flags.deleg", FT_BOOLEAN, 32,
2200                 TFS(&tfs_gss_flags_deleg), KRB5_GSS_C_DELEG_FLAG, NULL, HFILL }},
2201         { &hf_krb_gssapi_c_flag_mutual, {
2202                 "Mutual", "kerberos.gssapi.checksum.flags.mutual", FT_BOOLEAN, 32,
2203                 TFS(&tfs_gss_flags_mutual), KRB5_GSS_C_MUTUAL_FLAG, NULL, HFILL }},
2204         { &hf_krb_gssapi_c_flag_replay, {
2205                 "Replay", "kerberos.gssapi.checksum.flags.replay", FT_BOOLEAN, 32,
2206                 TFS(&tfs_gss_flags_replay), KRB5_GSS_C_REPLAY_FLAG, NULL, HFILL }},
2207         { &hf_krb_gssapi_c_flag_sequence, {
2208                 "Sequence", "kerberos.gssapi.checksum.flags.sequence", FT_BOOLEAN, 32,
2209                 TFS(&tfs_gss_flags_sequence), KRB5_GSS_C_SEQUENCE_FLAG, NULL, HFILL }},
2210         { &hf_krb_gssapi_c_flag_conf, {
2211                 "Conf", "kerberos.gssapi.checksum.flags.conf", FT_BOOLEAN, 32,
2212                 TFS(&tfs_gss_flags_conf), KRB5_GSS_C_CONF_FLAG, NULL, HFILL }},
2213         { &hf_krb_gssapi_c_flag_integ, {
2214                 "Integ", "kerberos.gssapi.checksum.flags.integ", FT_BOOLEAN, 32,
2215                 TFS(&tfs_gss_flags_integ), KRB5_GSS_C_INTEG_FLAG, NULL, HFILL }},
2216         { &hf_krb_gssapi_c_flag_dce_style, {
2217                 "DCE-style", "kerberos.gssapi.checksum.flags.dce-style", FT_BOOLEAN, 32,
2218                 TFS(&tfs_gss_flags_dce_style), KRB5_GSS_C_DCE_STYLE, NULL, HFILL }},
2219         { &hf_krb_gssapi_dlgopt, {
2220                 "DlgOpt", "kerberos.gssapi.dlgopt", FT_UINT16, BASE_DEC,
2221                 NULL, 0, "GSSAPI DlgOpt", HFILL }},
2222         { &hf_krb_gssapi_dlglen, {
2223                 "DlgLen", "kerberos.gssapi.dlglen", FT_UINT16, BASE_DEC,
2224                 NULL, 0, "GSSAPI DlgLen", HFILL }},
2225         { &hf_krb_midl_blob_len, {
2226                 "Blob Length", "kerberos.midl_blob_len", FT_UINT64, BASE_DEC,
2227                 NULL, 0, "Length of NDR encoded data that follows", HFILL }},
2228         { &hf_krb_midl_fill_bytes, {
2229                 "Fill bytes", "kerberos.midl.fill_bytes", FT_UINT32, BASE_HEX,
2230                 NULL, 0, "Just some fill bytes", HFILL }},
2231         { &hf_krb_midl_version, {
2232         "Version", "kerberos.midl.version", FT_UINT8, BASE_DEC,
2233         NULL, 0, "Version of pickling", HFILL }},
2234         { &hf_krb_midl_hdr_len, {
2235                 "HDR Length", "kerberos.midl.hdr_len", FT_UINT16, BASE_DEC,
2236                 NULL, 0, "Length of header", HFILL }},
2237         { &hf_krb_pac_signature_type, {
2238                 "Type", "kerberos.pac.signature.type", FT_INT32, BASE_DEC,
2239                 NULL, 0, "PAC Signature Type", HFILL }},
2240         { &hf_krb_pac_signature_signature, {
2241                 "Signature", "kerberos.pac.signature.signature", FT_BYTES, BASE_NONE,
2242                 NULL, 0, "A PAC signature blob", HFILL }},
2243         { &hf_krb_w2k_pac_entries, {
2244                 "Num Entries", "kerberos.pac.entries", FT_UINT32, BASE_DEC,
2245                 NULL, 0, "Number of W2k PAC entries", HFILL }},
2246         { &hf_krb_w2k_pac_version, {
2247                 "Version", "kerberos.pac.version", FT_UINT32, BASE_DEC,
2248                 NULL, 0, "Version of PAC structures", HFILL }},
2249         { &hf_krb_w2k_pac_type, {
2250                 "Type", "kerberos.pac.type", FT_UINT32, BASE_DEC,
2251                 VALS(w2k_pac_types), 0, "Type of W2k PAC entry", HFILL }},
2252         { &hf_krb_w2k_pac_size, {
2253                 "Size", "kerberos.pac.size", FT_UINT32, BASE_DEC,
2254                 NULL, 0, "Size of W2k PAC entry", HFILL }},
2255         { &hf_krb_w2k_pac_offset, {
2256                 "Offset", "kerberos.pac.offset", FT_UINT32, BASE_DEC,
2257                 NULL, 0, "Offset to W2k PAC entry", HFILL }},
2258         { &hf_krb_pac_clientid, {
2259                 "ClientID", "kerberos.pac.clientid", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
2260                 NULL, 0, "ClientID Timestamp", HFILL }},
2261         { &hf_krb_pac_namelen, {
2262                 "Name Length", "kerberos.pac.namelen", FT_UINT16, BASE_DEC,
2263                 NULL, 0, "Length of client name", HFILL }},
2264         { &hf_krb_pac_clientname, {
2265                 "Name", "kerberos.pac.name", FT_STRING, BASE_NONE,
2266                 NULL, 0, "Name of the Client in the PAC structure", HFILL }},
2267         { &hf_krb_pac_logon_info, {
2268                 "PAC_LOGON_INFO", "kerberos.pac_logon_info", FT_BYTES, BASE_NONE,
2269                 NULL, 0, "PAC_LOGON_INFO structure", HFILL }},
2270         { &hf_krb_pac_credential_type, {
2271                 "PAC_CREDENTIAL_TYPE", "kerberos.pac_credential_type", FT_BYTES, BASE_NONE,
2272                 NULL, 0, "PAC_CREDENTIAL_TYPE structure", HFILL }},
2273         { &hf_krb_pac_server_checksum, {
2274                 "PAC_SERVER_CHECKSUM", "kerberos.pac_server_checksum", FT_BYTES, BASE_NONE,
2275                 NULL, 0, "PAC_SERVER_CHECKSUM structure", HFILL }},
2276         { &hf_krb_pac_privsvr_checksum, {
2277                 "PAC_PRIVSVR_CHECKSUM", "kerberos.pac_privsvr_checksum", FT_BYTES, BASE_NONE,
2278                 NULL, 0, "PAC_PRIVSVR_CHECKSUM structure", HFILL }},
2279         { &hf_krb_pac_client_info_type, {
2280                 "PAC_CLIENT_INFO_TYPE", "kerberos.pac_client_info_type", FT_BYTES, BASE_NONE,
2281                 NULL, 0, "PAC_CLIENT_INFO_TYPE structure", HFILL }},
2282         { &hf_krb_pac_s4u_delegation_info, {
2283                 "PAC_S4U_DELEGATION_INFO", "kerberos.pac_s4u_delegation_info", FT_BYTES, BASE_NONE,
2284                 NULL, 0, "PAC_S4U_DELEGATION_INFO structure", HFILL }},
2285         { &hf_krb_pac_upn_dns_info, {
2286                 "UPN_DNS_INFO", "kerberos.pac_upn_dns_info", FT_BYTES, BASE_NONE,
2287                 NULL, 0, "UPN_DNS_INFO structure", HFILL }},
2288         { &hf_krb_pac_upn_flags, {
2289                 "Flags", "kerberos.pac.upn.flags", FT_UINT32, BASE_HEX,
2290                 NULL, 0, "UPN flags", HFILL }},
2291         { &hf_krb_pac_upn_dns_offset, {
2292                 "DNS Offset", "kerberos.pac.upn.dns_offset", FT_UINT16, BASE_DEC,
2293                 NULL, 0, NULL, HFILL }},
2294         { &hf_krb_pac_upn_dns_len, {
2295                 "DNS Len", "kerberos.pac.upn.dns_len", FT_UINT16, BASE_DEC,
2296                 NULL, 0, NULL, HFILL }},
2297         { &hf_krb_pac_upn_upn_offset, {
2298                 "UPN Offset", "kerberos.pac.upn.upn_offset", FT_UINT16, BASE_DEC,
2299                 NULL, 0, NULL, HFILL }},
2300         { &hf_krb_pac_upn_upn_len, {
2301                 "UPN Len", "kerberos.pac.upn.upn_len", FT_UINT16, BASE_DEC,
2302                 NULL, 0, NULL, HFILL }},
2303         { &hf_krb_pac_upn_upn_name, {
2304                 "UPN Name", "kerberos.pac.upn.upn_name", FT_STRING, BASE_NONE,
2305                 NULL, 0, NULL, HFILL }},
2306         { &hf_krb_pac_upn_dns_name, {
2307                 "DNS Name", "kerberos.pac.upn.dns_name", FT_STRING, BASE_NONE,
2308                 NULL, 0, NULL, HFILL }},
2309         { &hf_krb_pa_supported_enctypes,
2310           { "SupportedEnctypes", "kerberos.supported_entypes",
2311             FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
2312         { &hf_krb_pa_supported_enctypes_des_cbc_crc,
2313           { "des-cbc-crc", "kerberos.supported_entypes.des-cbc-crc",
2314             FT_BOOLEAN, 32, TFS(&supported_tfs), 0x00000001, NULL, HFILL }},
2315         { &hf_krb_pa_supported_enctypes_des_cbc_md5,
2316           { "des-cbc-md5", "kerberos.supported_entypes.des-cbc-md5",
2317             FT_BOOLEAN, 32, TFS(&supported_tfs), 0x00000002, NULL, HFILL }},
2318         { &hf_krb_pa_supported_enctypes_rc4_hmac,
2319           { "rc4-hmac", "kerberos.supported_entypes.rc4-hmac",
2320             FT_BOOLEAN, 32, TFS(&supported_tfs), 0x00000004, NULL, HFILL }},
2321         { &hf_krb_pa_supported_enctypes_aes128_cts_hmac_sha1_96,
2322           { "aes128-cts-hmac-sha1-96", "kerberos.supported_entypes.aes128-cts-hmac-sha1-96",
2323             FT_BOOLEAN, 32, TFS(&supported_tfs), 0x00000008, NULL, HFILL }},
2324         { &hf_krb_pa_supported_enctypes_aes256_cts_hmac_sha1_96,
2325           { "aes256-cts-hmac-sha1-96", "kerberos.supported_entypes.aes256-cts-hmac-sha1-96",
2326             FT_BOOLEAN, 32, TFS(&supported_tfs), 0x00000010, NULL, HFILL }},
2327         { &hf_krb_pa_supported_enctypes_fast_supported,
2328           { "fast-supported", "kerberos.supported_entypes.fast-supported",
2329             FT_BOOLEAN, 32, TFS(&supported_tfs), 0x00010000, NULL, HFILL }},
2330         { &hf_krb_pa_supported_enctypes_compound_identity_supported,
2331           { "compound-identity-supported", "kerberos.supported_entypes.compound-identity-supported",
2332             FT_BOOLEAN, 32, TFS(&supported_tfs), 0x00020000, NULL, HFILL }},
2333         { &hf_krb_pa_supported_enctypes_claims_supported,
2334           { "claims-supported", "kerberos.supported_entypes.claims-supported",
2335             FT_BOOLEAN, 32, TFS(&supported_tfs), 0x00040000, NULL, HFILL }},
2336         { &hf_krb_pa_supported_enctypes_resource_sid_compression_disabled,
2337           { "resource-sid-compression-disabled", "kerberos.supported_entypes.resource-sid-compression-disabled",
2338             FT_BOOLEAN, 32, TFS(&supported_tfs), 0x00040000, NULL, HFILL }},
2339         { &hf_krb_ad_ap_options,
2340           { "AD-AP-Options", "kerberos.ad_ap_options",
2341             FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
2342         { &hf_krb_ad_ap_options_cbt,
2343           { "ChannelBindings", "kerberos.ad_ap_options.cbt",
2344             FT_BOOLEAN, 32, TFS(&set_tfs), 0x00004000, NULL, HFILL }},
2345
2346 #include "packet-kerberos-hfarr.c"
2347         };
2348
2349         /* List of subtrees */
2350         static gint *ett[] = {
2351                 &ett_kerberos,
2352                 &ett_krb_recordmark,
2353                 &ett_krb_pac,
2354                 &ett_krb_pac_drep,
2355                 &ett_krb_pac_midl_blob,
2356                 &ett_krb_pac_logon_info,
2357                 &ett_krb_pac_s4u_delegation_info,
2358                 &ett_krb_pac_upn_dns_info,
2359                 &ett_krb_pac_server_checksum,
2360                 &ett_krb_pac_privsvr_checksum,
2361                 &ett_krb_pac_client_info_type,
2362                 &ett_krb_pa_supported_enctypes,
2363                 &ett_krb_ad_ap_options,
2364 #include "packet-kerberos-ettarr.c"
2365         };
2366
2367         static ei_register_info ei[] = {
2368                 { &ei_kerberos_decrypted_keytype, { "kerberos.decrypted_keytype", PI_SECURITY, PI_CHAT, "Decryted keytype", EXPFILL }},
2369                 { &ei_kerberos_address, { "kerberos.address.unknown", PI_UNDECODED, PI_WARN, "KRB Address: I don't know how to parse this type of address yet", EXPFILL }},
2370                 { &ei_krb_gssapi_dlglen, { "kerberos.gssapi.dlglen.error", PI_MALFORMED, PI_ERROR, "DlgLen is not the same as number of bytes remaining", EXPFILL }},
2371         };
2372
2373         expert_module_t* expert_krb;
2374         module_t *krb_module;
2375
2376         proto_kerberos = proto_register_protocol("Kerberos", "KRB5", "kerberos");
2377         proto_register_field_array(proto_kerberos, hf, array_length(hf));
2378         proto_register_subtree_array(ett, array_length(ett));
2379         expert_krb = expert_register_protocol(proto_kerberos);
2380         expert_register_field_array(expert_krb, ei, array_length(ei));
2381
2382         /* Register preferences */
2383         krb_module = prefs_register_protocol(proto_kerberos, kerberos_prefs_apply_cb);
2384         prefs_register_bool_preference(krb_module, "desegment",
2385         "Reassemble Kerberos over TCP messages spanning multiple TCP segments",
2386         "Whether the Kerberos dissector should reassemble messages spanning multiple TCP segments."
2387         " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2388         &krb_desegment);
2389 #ifdef HAVE_KERBEROS
2390         prefs_register_bool_preference(krb_module, "decrypt",
2391         "Try to decrypt Kerberos blobs",
2392         "Whether the dissector should try to decrypt "
2393         "encrypted Kerberos blobs. This requires that the proper "
2394         "keytab file is installed as well.", &krb_decrypt);
2395
2396         prefs_register_filename_preference(krb_module, "file",
2397                                    "Kerberos keytab file",
2398                                    "The keytab file containing all the secrets",
2399                                    &keytab_filename, FALSE);
2400 #endif
2401
2402 }
2403 static int wrap_dissect_gss_kerb(tvbuff_t *tvb, int offset, packet_info *pinfo,
2404                                  proto_tree *tree, dcerpc_info *di _U_,guint8 *drep _U_)
2405 {
2406         tvbuff_t *auth_tvb;
2407
2408         auth_tvb = tvb_new_subset_remaining(tvb, offset);
2409
2410         dissect_kerberos_main(auth_tvb, pinfo, tree, FALSE, NULL);
2411
2412         return tvb_captured_length_remaining(tvb, offset);
2413 }
2414
2415
2416 static dcerpc_auth_subdissector_fns gss_kerb_auth_connect_fns = {
2417         wrap_dissect_gss_kerb,                      /* Bind */
2418         wrap_dissect_gss_kerb,                      /* Bind ACK */
2419         wrap_dissect_gss_kerb,                      /* AUTH3 */
2420         NULL,                                       /* Request verifier */
2421         NULL,                                       /* Response verifier */
2422         NULL,                                       /* Request data */
2423         NULL                                        /* Response data */
2424 };
2425
2426 static dcerpc_auth_subdissector_fns gss_kerb_auth_sign_fns = {
2427         wrap_dissect_gss_kerb,                      /* Bind */
2428         wrap_dissect_gss_kerb,                      /* Bind ACK */
2429         wrap_dissect_gss_kerb,                      /* AUTH3 */
2430         wrap_dissect_gssapi_verf,                   /* Request verifier */
2431         wrap_dissect_gssapi_verf,                   /* Response verifier */
2432         NULL,                                       /* Request data */
2433         NULL                                        /* Response data */
2434 };
2435
2436 static dcerpc_auth_subdissector_fns gss_kerb_auth_seal_fns = {
2437         wrap_dissect_gss_kerb,                      /* Bind */
2438         wrap_dissect_gss_kerb,                      /* Bind ACK */
2439         wrap_dissect_gss_kerb,                      /* AUTH3 */
2440         wrap_dissect_gssapi_verf,                   /* Request verifier */
2441         wrap_dissect_gssapi_verf,                   /* Response verifier */
2442         wrap_dissect_gssapi_payload,                /* Request data */
2443         wrap_dissect_gssapi_payload                 /* Response data */
2444 };
2445
2446
2447
2448 void
2449 proto_reg_handoff_kerberos(void)
2450 {
2451         dissector_handle_t kerberos_handle_tcp;
2452
2453         krb4_handle = find_dissector_add_dependency("krb4", proto_kerberos);
2454
2455         kerberos_handle_udp = create_dissector_handle(dissect_kerberos_udp,
2456         proto_kerberos);
2457
2458         kerberos_handle_tcp = create_dissector_handle(dissect_kerberos_tcp,
2459         proto_kerberos);
2460
2461         dissector_add_uint_with_preference("udp.port", UDP_PORT_KERBEROS, kerberos_handle_udp);
2462         dissector_add_uint_with_preference("tcp.port", TCP_PORT_KERBEROS, kerberos_handle_tcp);
2463
2464         register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_CONNECT,
2465                                                                           DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
2466                                                                           &gss_kerb_auth_connect_fns);
2467
2468         register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY,
2469                                                                           DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
2470                                                                           &gss_kerb_auth_sign_fns);
2471
2472         register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
2473                                                                           DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
2474                                                                           &gss_kerb_auth_seal_fns);
2475 }
2476
2477 /*
2478  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
2479  *
2480  * Local variables:
2481  * c-basic-offset: 8
2482  * tab-width: 8
2483  * indent-tabs-mode: t
2484  * End:
2485  *
2486  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2487  * :indentSize=8:tabSize=8:noTabs=false:
2488  */