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